Golang inferred interfaces

1.4k views Asked by At

Just a simple language design related question here. In languages like Swift, in order for a struct/class to conform to a protocol/interface, one needs to explicitly declare it as such

struct Dog: Animal {
    // implementation of Animal protocols here
}

But why is it that in Go, there are no explicit ways to show what interfaces a struct conforms to?

Isn't this just making things unclear or are there any other reasons behind it?

2

There are 2 answers

0
VonC On BEST ANSWER

This allow to evolve to provide interface even for legacy types (which never explicitly declared respecting said interface)

If those types already provide the right methods (ie the same API as the one specified by your interface), they will satisfy that interface.

That allows to maintain a low coupling between those legacy types (which have no idea your interface exist) and your program, which accepts instances of that interface.

See "What are some examples of Go interfaces?"

Go's interfaces aren't a variant on Java or C# interfaces, they're much more.
They are a key to large-scale programming and adaptable, evolutionary design.

"It's the fact that I don't have to spend time up front designing some sort of type hierarchy and then rearranging it two or three times before I finish.
It's not even the fact that it's easy to do it right -
it's the fact that I just don't have to worry about it and can get on with the actual algorithm."

Those quotes are from this 2012 article, and also from this thread, where you can read Rob Pike's comment:

"It's always bothered me in OO languages that we can make Circle, Square, etc. subclasses of Shape (say), but that's the one design decision we get to make.
What if we want to align those things along other axes (so to speak), like topological genus or plant genus, if you're a landscaper? You might lose your way or dig yourself into a hole with multiple inheritance."

0
icza On

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.