【发布时间】:2020-10-13 19:29:05
【问题描述】:
我几天前刚开始学习 Go。今天,我们在调试一段代码时发现了一些似乎与 Go 有悖常理的事情。
首先我们定义了一个接口和一个实现它的数据结构。
type Executer interface {
Execute()
}
type whatever struct {
name string
}
func (this *whatever) Execute() {
log.Println(this.name)
}
现在考虑我有一个指向 whatever 的 nil 指针,我尝试调用方法 Execute。在我迄今为止使用的其他面向对象语言中,这将在调用方法时调用空指针错误(即w.Execute()),因为对象指针为空。有趣的是,在 Go 中,调用该方法时,当我尝试取消引用 this.name 时,Execute 方法出现空指针错误。为什么不在调用方法的时候?
func main() {
var w *whatever
w.Execute()
}
那么,我现在想要了解的是,这怎么可能?这是否意味着 Go 只在编译时进行早期方法绑定,而在运行时没有方法与特定对象的绑定?
【问题讨论】:
-
接收者只是函数的一个“普通”参数。如果是指针,它可能是
nil。在 Java 中,您也可以在null对象上调用静态方法。 -
这是
nil接收者的用例:Test for nil values in nested stucts -
@icza 有趣!我没有考虑过这个角度。虽然,当 Java 中的方法是静态的时,我可以通过执行
T.method()调用它时遵循更好的模式,其中T是一个类型,而不是obj.method()其中obj是一个对象。看来我在 Go 中无法做到这一点,因为如果不将其绑定到特定的struct,界面就会毫无生气。调用的风格让我感到困惑,让我相信struct的实例是目标,看来是struct类型绑定它。 -
是的,因为 Go 更简单:没有 static、public、protected、private、package private 等修饰符。在 Go 中,只有导出和非导出。但是 Go 也有一些好处:方法表达式和值。见golang function alias on method receiver;和Pass method argument to function。
-
@velkor 明白了。所有绑定都是在编译时完成的,对吧?现在已经澄清,方法的行为方式与其他语言(如 Java 或 C#)中的静态方法类似。
标签: go pointers methods binding