已经阅读了很多,但指针接收器和价值接收器之间的二分法仍然让我感到困惑。
我们说我们有这个......
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
。该规则仍然执行 - 虽然"在场景后面#34;。
该规则虽然在接口中断言。
我们说我们有一个界面......
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编译器为我们提供的帮助"遗忘"关于这个规则 - 特别是在方法调用表达式中。
答案 0 :(得分:-1)
尝试修改a.color
方法中的Eat()
,并在致电a.color
后在main()
打印a.Eat()
。
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)
}
然后将Eat()
方法的参数更改为非指针。在这两种情况下,您都会看到它按预期工作。
实际回答你的问题:go编译器自动确定你是需要值还是指针。如果你有一个指针并调用一个值接收器方法,这也可以反过来。