这个问题在这里已有答案:
一直在阅读它,但指针接收器和 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
是值) . 但是这会编译并运行和打印 .
我的理解是,如果 a
是一个指针,那么它将适用于值接收器和指针接收器方法 . 但是当 a
是一个值时,它应该只适用于具有值接收器的方法,因为指针接收器方法不在方法集中 .
但上述似乎与此相矛盾 . 这是怎么回事 . (我正在运行Go 1.8.3
) .
https://play.golang.org/p/eWkDHwIgOZ
- 更新 -
事实证明有两件事需要注意 .
第一个是实际规则,第二个是我们使用这些接收器获得的编译器辅助 .
规则是指针接收器方法不能通过值调用 - 它必须是一个指针 . 但是当我们调用 a.Eat
( a
是一个值)时 - 编译器会帮助它并将 a
转换为 &a
. 该规则仍然执行 - 尽管"behind the scene" .
该规则虽然在接口中断言 .
假设我们有一个界面......
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编译器提供给我们“忘记”这个规则 - 特别是在方法调用表达式中 .
1 回答
尝试在
Eat()
方法中修改a.color
,并在调用a.Eat()
后在main()
中打印a.color
.然后将
Eat()
方法的参数更改为非指针 . 在这两种情况下,您都会看到它按预期工作 .要实际回答您的问题:go编译器会自动确定您是需要值还是指针 . 如果你有一个指针并调用一个值接收器方法,这也可以反过来 .