【问题标题】:Go - how to explicitly state that a structure is implementing an interface?Go - 如何明确声明一个结构正在实现一个接口?
【发布时间】:2015-10-23 13:15:46
【问题描述】:

由于 Go 非常重视接口,我想知道如何明确声明一个结构正在实现接口,以便在缺少某些方法的情况下进行清晰和错误检查?到目前为止,我已经看到了两种方法,我想知道哪种方法是正确的并且符合 Go 规范。

方法 1 - 匿名字段

type Foo interface{
    Foo()
}

type Bar struct {
    Foo
}
func (b *Bar)Foo() {
}

方法 2 - 显式转换

type Foo interface{
    Foo()
}

type Bar struct {
}
func (b *Bar)Foo() {
}
var _ Foo = (*Bar)(nil)

这些方法是正确的,还是有其他方法可以做这样的事情?

【问题讨论】:

标签: inheritance go interface standards


【解决方案1】:

你不能。在 Go 中,所有接口实现都是隐式的。您可以检查一个类型是否实现了一个接口(这是它获得的最明确的接口)。如果我在我从事的一个项目中没记错的话,我们只是在包的顶部针对该类型实现的接口进行了一些类型断言,这与它所获得的一样接近显式。

【讨论】:

  • 确实如此。这是语言设计者深思熟虑的决定。
  • They mention the var _ trick in the FAQ,所以虽然他们确实决定不包括“实施”,但他们似乎并不太反对黑客入侵支票。
  • @twotwotwo 是的,它是有价值的。开发人员正在寻找的行为仍然存在,您的组织/项目是否使用它取决于您。一般来说,Go 是渐进式的,什么是语言的一部分,什么不是。我认为他们的大多数决定都非常好,包括这个。
【解决方案2】:

方法 2 是正确的,方法 1 只是嵌入一个类型并覆盖其功能。如果你忘记覆盖它,你最终会得到一个 nil 指针解引用。

【讨论】:

  • 如果您认为这是一个测试(我愿意),您会将var _ … 行放入您的*_test.go 文件之一。如果类型不是指针(例如,如果它是实现接口的Bar 而不是*Bar),您可以使用var _ Foo = Bar{}
  • 我个人更喜欢将它添加到我的类型上方,以确保我不会意外破坏它,但是 ymmv。
【解决方案3】:

我很少需要声明这一点,因为在我的包中几乎总是有某个地方我使用结构作为接口。我倾向于遵循在可能的情况下保持我的结构不暴露的模式,并且只通过“构造函数”函数提供它们。

type Foo interface{
  Foo()
}

type bar struct {}
func (b *bar)Foo() {}

func NewBar() Foo{
  return &bar{}
}

如果bar 不满足Foo,则不会编译。我没有添加构造来声明该类型实现了接口,而是确保 my 代码在某些时候将其用作接口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多