Reputation: 338
Here is an example of the idea 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's 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 method Get
to return an interface A
C
has a member function Get
to return a pointer to struct CA
, which implements interface A
The result is Go can't deduce interface B
from struct C
, even their Get
method is only different in returning type, which is convertible.
The reason I raise this question is when interface A, B and struct C, CA are in different packages, I can only:
C
to func Get() A, which introduce some dependency between packages.Get
method of interface B
and struct C
to func Get() interface{}I want to avoid dependency between packages and try not to rely on interface{}, can anyone give me some hint? What's the best practice in Go?
Upvotes: 3
Views: 2901
Reputation: 417462
Your current *C
type does not implement the interface B
, therefore you can't assign a value of *C
to a variable of type B
nor can't you "type assert" a value of B
from something holding a value of type *C
.
Here's what you can do. Since you're already using a struct literal (&C{}
), you may declare c
to be of type *C
of which you can call its Get()
method, and you can convert the return value of C.Get()
to A
(because the return value does implement 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's CA
it's CA
Or refactor:
The problem is that you have an interface (B
) which you want to implement, which has a method which returns another interface (A
). To implement this B
interface, you have to have dependency to the package that defines A
, you can't avoid this. And you have to declare C.Get()
to return A
(instead of a concrete struct type).
You may move A
to a 3rd package and then the package that defines C
will only have to depend on this 3rd package, but will not depend on the package that defines B
(but still will implicitly implement the interface type B
).
Upvotes: 3