OK. I know this is a FAQ, and I think the answer is "give up, it doesn't work that way", but I just want to make sure I'm not missing something.
I am still wrapping my head around best practices and rules for use of interfaces. I have code in different packages that I'd prefer to keep decoupled, something like so (doesn't work, or I wouldn't be here):
package A
type Foo struct {}
func (f *Foo) Bars() ([]*Foo, error) {
foos := make([]*Foo, 0)
// some loop which appends a bunch of related *Foo to foos
return foos, nil
}
package B
type Foolike interface {
Bars() []Foolike
}
func DoSomething(f Foolike) error {
// blah
}
With this, the compiler complains:
cannot use f (type *A.Foo) as type Foolike in argument to B.DoSomething:
*A.Foo does not implement Foolike (wrong type for Bars method)
have Bars() ([]*A.Foo, error)
want Bars() ([]Foolike, error)
Now, I grok that []Foolike is not an interface signature itself; it's the signature for a slice of Foolike interfaces. I think I also grok that the compiler treats []*A.Foo and []Foolike as different things because ... (mumble memory allocation, strict typing mumble).
My question is: Is there a correct way to do what I ultimately want, which is to let B.DoSomething() accept an *A.Foo without having to import A and use *A.Foo in B.DoSomething()'s function signature (or worse, in the interface definition)? I'm not hung up on trying to trick the compiler or get into crazy runtime tricks. I understand that I could probably change the implementation of Foo.Bars() to return []Foolike, but that seems stupid and wrong (Why should A have to know anything about B? That breaks the whole point of decoupling things!).
I guess another option is to remove Bars() as a requirement for implementing the interface and rely on other methods to enforce the requirement. That feels less than ideal, though (what if Bars() is the only exported method?). Edit: No, that won't work because then I can't use Bars() in DoSomething(), because it's not defined in the interface. Sigh.
If I'm just Doing It Wrong™, I'll accept that and figure something else out, but I hope I'm just not getting some aspect of how it's supposed to work.