Go 指针接收器与值接收器混淆
我已经读了很多,但是指针接收器和值接收器之间的二分法仍然让我困惑 假设我们有这个Go 指针接收器与值接收器混淆,go,Go,我已经读了很多,但是指针接收器和值接收器之间的二分法仍然让我困惑 假设我们有这个 type Apple struct { color string } func (a *Apple) Eat() { fmt.Printf("Eating %s apple\n", a.color) } func main() { a := Apple{"red"} a.Eat() } 我认为这是一个错误,因为我们试图通过一个值(ais value)调用一个带有指针接收器的方
type Apple struct {
color string
}
func (a *Apple) Eat() {
fmt.Printf("Eating %s apple\n", a.color)
}
func main() {
a := Apple{"red"}
a.Eat()
}
我认为这是一个错误,因为我们试图通过一个值(a
is value)调用一个带有指针接收器的方法。但这是编译、运行和打印的
我的理解是,如果a
是指针,那么它将适用于值接收器和指针接收器方法。但是当a
是一个值时,它应该只适用于具有值接收器的方法,因为指针接收器方法不在方法集中
但上述情况似乎与此相矛盾。发生什么事。(我正在运行Go1.8.3
)
--更新--
事实证明有两件事需要注意
第一个是实际规则,第二个是我们在使用这些接收器时得到的编译器帮助
规则是指针接收器方法不能通过值调用——它必须是指针。但是当我们调用a.Eat
(a
是一个值)时,编译器会伸出援助之手,将a
变成&a
。这项规定仍然在执行——尽管“在幕后”
不过,该规则在接口中声明自己
假设我们有一个接口
type Edible interface {
Eat()
}
// Note that this is not a method, it is a simple function.
func EatMore(x Edible) {
fmt.Println("Eating more...")
x.Eat()
}
func main() {
a := Apple{"red"}
a.Eat() // Okay -- because compiler is helping
EatMore(a) // Wrong -- the rule asserts, compiler does not help
}
这里,在对EatMore(a)
的调用中,编译器没有将a
转换为&a
——因此我们得到了错误。正如预期的那样,正确的方法是,EatMore(&a)
因此,区分该规则与帮助Go编译器为我们提供的“忘记”该规则的帮助非常重要——特别是在方法调用表达式中
在调用
a.Eat()
后,尝试在Eat()方法中修改a.color
,并在main()中打印a.color
然后将Eat()
方法的参数更改为非指针。您将看到它在这两种情况下都能正常工作
要真正回答您的问题:go编译器会自动确定您是需要值还是指针。如果您有一个指针并调用一个值接收器方法,那么这也是另一种方式
func (a *Apple) Eat() {
a.color = "green"
fmt.Printf("Eating %s apple", a.color)
}
func main() {
a := Apple{"red"}
a.Eat()
fmt.Printf("Eating %s apple", a.color)
}