Implicit interface conversion to golang
Here is an example of an idea that I want to demonstrate.
package main
import "fmt"
// interface declaration
//
type A interface {
AAA() string
}
type B interface{
Get() A
}
// implementation
//
type CA struct {}
// implementation of A.AAA
func (ca *CA) AAA() string {
return "it CA"
}
type C struct {}
// implementation of B.Get, except for returning a 'struct' instead of an 'interface'
func (c *C) Get() *CA {
return &CA{}
}
func main() {
var c interface{} = &C{}
d := c.(B)
fmt.Println(d.Get().AAA())
fmt.Println("Hello, playground")
}
In this example
-
B
has a methodGet
to return an interfaceA
- struct
C
has a member functionGet
to return a pointer to a structCA
that implements the interfaceA
As a result, Go cannot infer an interface B
from a struct C
, even their method Get
differs only from the return type, which is convertible.
The reason I am raising this question is when interface A, B and struct C, CA are in different packages, I can only:
- refine the Get method from
C
to func Get () A , which introduces some dependency between packages. - refine the
Get
interface methodB
and structC
to func Get () interface {}
I want to avoid dependency between packages and try not to rely on the {} interface , can anyone give me some hint? What's the best practice in Go?
source to share
Your current type *C
does not implement an interface B
, so you cannot assign a value to *C
a type variable, B
and you cannot "type assert" a value B
from something containing a value of the type *C
.
Here's what you can do. Since you are already using the struct ( &C{}
) literal , you can declare a c
type *C
you can call it a method Get()
, and you can convert the return value C.Get()
to A
(because the return value implements A
):
var c *C = &C{}
var a A = c.Get() // This is ok, implicit interface value creation (of type A)
fmt.Println(a.AAA())
// Or without the intermediate "a", you can simply call:
fmt.Println(c.Get().AAA())
Output:
it CA
it CA
Or refactoring:
The problem is that you have an interface ( B
) that you want to implement, which has a method that returns another interface ( A
). To implement this interface B
, you must have a dependency on the package that defines A
, you cannot avoid it. And you must declare C.Get()
to return A
(instead of a specific struct type).
You can move A
to a third package, and the package that defines c
will only have to depend on that third package, but will not depend on the package that defines B
(but will still implicitly implement the interface type B
).
source to share