Extending VonC's answer.
From the question:
But why is it that in Go, there are no explicit ways to show what interfaces a struct conforms to?
Actually there are some ways. See Go FAQ: How can I guarantee my type satisfies an interface?
Let's say we have the following interface:
type Sayer interface {
Say() string
}
And we want to create a new type implementing it:
type MySayer struct{}
func (ms MySayer) Say() string {
return "Foo"
}
In this case MySayer
implements Sayer
. To make sure it does, you can add the following line:
var _ Sayer = MySayer{}
Should you mistype something, e.g. name your Say()
method Sai()
, it will be a compile-time error.
Still, this is just a compile-time "check", and it does not document that MySayer
implements Sayer
. For this purpose you may add a "dummy" method whose name itself documents this property:
type Sayer interface {
Say() string
ImplementsSayer()
}
Now for any type to implement Sayer
, they must declare a method named ImplementsSayer()
, which judged by just a glimpse tells you it implements Sayer
:
func (MySayer) ImplementsSayer() {}
You don't even need to name the receiver as it is not used. The line reads in plain English: "MySayer implements Sayer".
Since this method is exported (starts with a capital letter), it also appears in docs, telling in your face that it implements Sayer
. But as the FAQ says:
Most code doesn't make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they're necessary to resolve ambiguities among similar interfaces.