Golang 推断接口

Golang inferred interfaces

这里只是一个简单的语言设计相关问题。 在像 Swift 这样的语言中,为了使 struct/class 符合 protocol/interface,需要明确声明它

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

但为什么在 Go 中,没有明确的方法来显示结构符合哪些接口?

这不是说不清楚还是另有原因?

这允许进化为甚至为遗留类型(从未明确声明尊重所述接口)提供接口

如果这些类型已经提供了正确的方法(即与您的接口指定的方法相同 API),它们将满足该接口。

这允许在那些遗留类型(不知道你的接口存在)和你的程序之间保持低耦合,它接受该接口的实例。

参见“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."

这些引述来自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."

扩展 VonC 的答案。

来自问题:

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

其实有一些方法。参见 Go FAQ: How can I guarantee my type satisfies an interface?

假设我们有以下接口:

type Sayer interface {
    Say() string
}

我们想创建一个新类型来实现它:

type MySayer struct{}

func (ms MySayer) Say() string {
    return "Foo"
}

在这种情况下 MySayer 实现 Sayer。为确保它确实如此,您可以添加以下行:

var _ Sayer = MySayer{}

如果您输入错误,例如将您的 Say() 方法命名为 Sai(),这将是一个编译时错误。

不过,这只是编译时 "check",它没有记录 MySayer 实现 Sayer。为此,您可以添加一个 "dummy" 方法,其 name 本身 记录此 属性:

type Sayer interface {
    Say() string
    ImplementsSayer()
}

现在任何类型要实现 Sayer,它们都必须声明一个名为 ImplementsSayer() 的方法,一眼就能判断出它实现了 Sayer:

func (MySayer) ImplementsSayer() {}

您甚至不需要为接收器命名,因为它不被使用。该行用简单的英语显示:"MySayer implements Sayer".

由于这个方法是导出的(以大写字母开头),它也出现在文档中,当面告诉你它实现了Sayer。但正如常见问题解答所说:

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.