I'm trying to get Go interfaces to work, and the problem I am having is that a Go interface method returning a go interface only works if the implementation declares the interface and not a concrete type that implements the interface.
In the following example I receive:
prog.go:29: cannot use &f (type *Bar) as type StringerGetter in argument to Printer: *Bar does not implement StringerGetter (wrong type for GetStringer method) have GetStringer() *Foo want GetStringer() fmt.Stringer
package main
import "fmt"
type Foo struct {
val string
}
func (f *Foo) String() string {
return f.val
}
type StringerGetter interface {
GetStringer() fmt.Stringer
}
type Bar struct{}
func (b *Bar) GetStringer() *Foo {
return &Foo{"foo"}
}
func Printer(s StringerGetter) {
fmt.Println(s.GetStringer())
}
func main() {
f := Bar{}
Printer(&f)
}
However if I change func (b *Bar) GetStringer() *Foo { to func (b *Bar) GetStringer() fmt.Stringer { it works as expected.
Foo does fulfill fmt.Stringer
The rub is that the above is simple example code illustrating the problem.
In the case of the code I am trying to write, the interfaces I created are in my "main" package, whereas the concrete types I'm writing interfaces against are in a 3rd party package I'd prefer not to modify.
I want to be able to write my own structs as well that fulfill said interfaces, so interfacing against the concrete return type isn't an option either.
I have to assume there is a way to do this.
Foois because the interface says it returns afmt.Stringer. This is not isolated to Go. For example, this C# code also fails because of the same reason: dotnetfiddle.net/4xZ2tk. The compiler simply cannot guarantee that you're going to return an object that satisfies the interface unless you tell it that you promise you will (by having the signature match the interface).