Clashing method names in Go interfaces
I wrote about how the Go and C# compilers implement interfaces and mentioned how C# deals with clashing method names but I didn’t talk about how Go does it, so here it is.
Two interfaces with the same method name that need to behave differently is very likely a sign of bad API design and we should fix it instead. But sometimes we can’t help it (e.g. the interfaces are part of a third-party package). How do we deal with it then? Let’s see.
Given two interfaces
type Firster interface {
DoSomething()
}
type Seconder interface {
DoSomething()
}
We implement them like this
type MyStruct struct{}
func (ms MyStruct) DoSomething() {
log.Println("Doing something")
}
We can run this little test here to verify that MyStruct
implements both interfaces.
But what if we need DoSomething()
to do something different depending on whether MyStruct
is being cast as Firster
or Seconder
?
Go doesn’t support any kind of explicit declaration of interfaces when implementing methods. We can’t do something like, say
type MyStruct struct{}
func (ms MyStruct) Firster.DoSomething() {
log.Println("Doing something")
}
func (ms MyStruct) Seconder.DoSomething() {
log.Println("Doing something")
}
That won’t work. The solution is to wrap MyStruct
with a new type that reimplements DoSomething()
. Like this
type SeconderWrapper struct {
MyStruct
}
func (sw SeconderWrapper) DoSomething() {
log.Println("Doing something different")
}
Now when we need to pass it to a function expecting Seconder
, we can wrap MyStruct
ms := MyStruct{}
useSeconder(SeconderWrapper{ms})
That will run the DoSomething()
from SeconderWrapper
. When passing it as Firster
, the original DoSomething()
will be called instead. You can see this in action here.