考虑以下简单程序,我们在指向struct Vertex
的指针上定义一个方法,然后用指针调用它。
package main
import (
"fmt"
)
type Vertex struct {
X, Y float64
}
func (v *Vertex) Mutate() {
v.X = 8
}
func main() {
v := &Vertex{3, 4}
v.Mutate()
fmt.Println(v.X)
}
这个程序的输出是8
,我们期望这是因为我们传递一个指向带指针的方法的指针。
但是,以下调用的输出也为8。
func main() {
v := Vertex{3, 4}
v.Mutate()
fmt.Println(v.X)
}
对称地,如果我们重新定义方法Mutate
以取Vertex
而不是指针,那么无论指针或结构是否通过,突变都会失败。
这种行为似乎意味着参数v
或指向v
的指针是否完全取决于方法的定义,而不是实际传递的内容。
这是正确的解释吗?这种情况总是如此吗?如果没有,这种行为的正确解释是什么?
答案 0 :(得分:3)
这种行为似乎意味着参数v或指向v的指针是否完全取决于方法的定义,而不是实际传递的内容。
这是正确的解释吗?这种情况总是如此吗?如果没有,这种行为的正确解释是什么?
不,这不正确,但几乎是正确的。
传递给您的方法的内容是指针,即使它看起来像v.Mutate()
v
非指针。原因是:您的v
是"可寻址"因此其方法集包括指针类型的方法。有关详细信息,请参阅http://golang.org/ref/spec#Calls。这是一种语法糖。由于v
是可寻址的,因此您可以使用其地址&v
,并且可以在此指针上调用您的方法(&v).Mutate
。这种语法很笨拙,Go会自动为你做可寻址的表达式。
(如果您对这些内容感兴趣,为什么不阅读整个语言规范?可以在3个小时内完成。)