【问题标题】:Interface implementation enforcement in GoGo中的接口实现强制
【发布时间】:2021-12-14 03:07:15
【问题描述】:

我有简单的 Go 代码:

type MyInterface interface {
    Do()
}

type Doer struct{}

func (d *Doer) Do() {}

// Option 1
var _ MyInterface = (*Doer)(nil)

// Option 2
var _ MyInterface = &Doer{}

与选项 2 相比,使用选项 1(广泛使用并建议在任何地方)强制执行接口的缺点是什么?

如果我们丢弃结果,实例化一个真实对象而不是指针有什么害处?

我知道选项 2 可能会慢一毫秒,因为它为结构分配内存,而且 GC 可能还有一毫秒的时间来清理它,但所有这些都只发生在启动时,不会影响运行时。

这些是我的正确还是我错过了什么?

【问题讨论】:

  • 这是一个编译时强制检查 - 所以不要想太多并选择选项 1,因为它对运行时的影响为零。
  • 它们都是有效的MyInterface 值,但两者并不相同。 (*Doer)(nil) 是一个指向 Doer 的 nil 指针。 &Doer{} is 指向已分配内存的指针。通常,现实生活中的结构具有需要初始化的成员,因此在这些情况下不适合使用 nil 指针。
  • 旁注:Go 命名约定使用x-er 作为接口 的名称,因此Doer 将是具有Do 函数的接口的名称, Reader 的方式是具有 Read 函数的字节和字符串读取器的名称。如果有一个 Do 用于它,那么具有某些结构的实际具体实现可能是一个 符合 Doer 实现的 struct X
  • what's the harm of instantiating a real object instead of pointer? 很少,如果没有的话。它只是一个包级变量。你可以相信 Go 团队已经考虑到这一点并采取了最适当的行动。最后,在疑问中,如果您在核心语言的代码中发现了这种做法,那么即使您不了解所有错综复杂的内容,也可以安全地复现。

标签: go interface


【解决方案1】:

问题中的分析很好。这里还有两点:

选项 1 适用于任何类型。选项 2 仅适用于具有复合文字语法的类型。

这是一个例子:

type IntDoer int

func (d *IntDoer) Do() {}

// Option 1
var _ MyInterface = (*IntDoer)(nil)

// Option 2 DOES NOT COMPILE
var _ MyInterface = &IntDoer{} 

选项 2 可能没有任何运行时损失。编译器可能会优化分配。

【讨论】:

  • 我明白了。在这种情况下,我可以使用可以处理这两种情况的var _ MyInterface = new(Doer)
猜你喜欢
  • 2015-05-08
  • 2013-02-19
  • 2015-10-23
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多