【发布时间】: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 团队已经考虑到这一点并采取了最适当的行动。最后,在疑问中,如果您在核心语言的代码中发现了这种做法,那么即使您不了解所有错综复杂的内容,也可以安全地复现。