考虑下面的简单程序,我们在指向 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
的指针是否传递完全取决于方法的定义,而不是实际传递的内容通过了。
这是正确的解释吗?情况总是如此吗?如果不是,这种行为的正确解释是什么?
最佳答案
This behavior seems to imply that whether the argument v or a pointer to v to passed depends entirely on the definition of the method, rather than on what is actually being passed.
Is this a correct interpretation, and will this always be the case? If not, what is the correct explanation for this behavior?
不,这不正确,但几乎是正确的。
传递给方法的是一个指针,即使它看起来像 v.Mutate()
和 v
是一个非指针。原因是:您的 v
是“可寻址的”,因此它的方法集包括指针类型上的方法。请参阅http://golang.org/ref/spec#Calls了解详情。这是一种语法糖。因为 v
是可寻址的,所以您可以获取其地址 &v
,并在此指针上调用您的方法,例如 (&v).Mutate
。这种语法很笨拙,Go 会自动为您处理可寻址表达式。
(如果你对这些东西感兴趣,为什么不阅读整个语言规范?3小时内就能完成。)
关于go - 结构体方法的参数传递语义是否完全由方法而不是调用者决定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31149191/