指针接收器与值接收器混淆

时间:2017-06-27 12:28:55

标签: 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()
}

我认为这是一个错误,因为我们试图通过值(a是值)调用指针接收器的方法。但是这会编译并运行和打印。

我的理解是,如果a是指针,那么它将适用于值接收器和指针接收器方法。但是当a是一个值时,它应该只适用于具有值接收器的方法,因为指针接收器方法不在方法集中。

但上述似乎与此相矛盾。发生了什么事。 (我正在运行Go 1.8.3)。

https://play.golang.org/p/eWkDHwIgOZ

- 更新 -

原来有两点需要注意。

首先是实际规则,其次是我们使用这些接收器获得的编译器辅助。

规则是指针接收器方法不能通过值调用 - 它必须是指针。但是,当我们调用a.Eata为值)时,编译器会帮助将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编译器为我们提供的帮助"遗忘"关于这个规则 - 特别是在方法调用表达式中。

https://play.golang.org/p/p3-LUlbmCg

1 个答案:

答案 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编译器自动确定你是需要值还是指针。如果你有一个指针并调用一个值接收器方法,这也可以反过来。