I'm writing a piece of code that relies on some implementation.
I want to decouple the implementation from my code, and make the implementation as independent as possible.
I thought of achieving this approach by using interfaces instead of concrete types, like so:
package mypackage
type MyType interface {
Title() string
Price() int
}
type TypeGetter interface {
GetType() MyType
}
func MyHandler(tg TypeGetter) {
t := tg.GetType()
fmt.Printf("Title: %s, Price: %d", t.Title(), t.Price())
}
And an implementation might be something like this:
package external
// CustomType implicitly implements the MyType interface
type CustomType struct {
title string
price int
}
func (t CustomType) Title() string { return t.title }
func (t CustomType) Price() int { return t.price }
// CustomTypeGetter implicitly implements the TypeGetter interface. Or is it???
type CustomTypeGetter struct {
}
func (g CustomTypeGetter) GetType() CustomType {
return CustomType{"Hello", 42}
}
Then, the code would do something like this:
package main
import "mypackage"
import "external"
func main() {
tg := external.CustomTypeGetter{}
mypackage.MyHandler(tg) // <--- the compiler does not like this
}
I hope the example speaks for itself: I have no coupling between "mypackage" and the "external" package, which may be replaced, substituted my mocks for testing, etc.
The problem: the compiler complains that the call to MyHandler has an object that implements:
func GetType() CustomType, instead of:
func GetType() MyType
The only solution I found is to move the interface declarations (MyType and TypeGetter) to a third package, and then both "mypackage" and "external" packages can use it.
But I want to avoid that.
Isn't Go's concept of implicit implementation of interfaces contradict the idea of a third common package?
Is there a way to implement such thing, without binding the two packages together?