首页 文章

指针接收器与值接收器混淆[重复]

提问于
浏览
2

这个问题在这里已有答案:

一直在阅读它,但指针接收器和 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.Eata 是一个值)时 - 编译器会帮助它并将 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编译器提供给我们“忘记”这个规则 - 特别是在方法调用表达式中 .

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

1 回答

  • -1

    尝试在 Eat() 方法中修改 a.color ,并在调用 a.Eat() 后在 main() 中打印 a.color .

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

相关问题