首页 文章

为什么带有指针接收器的方法在收到值时仍然有效?

提问于
浏览
4

我只是在玩Exercise 51 in the Tour of Go . 该解释声称 Scale 方法在收到 Vertex 而不是指向 Vertex 的指针时无效 .

然而,当我在 main 中将声明 v := &Vertex{3, 4} 更改为 v := Vertex{3, 4} 时,输出中唯一的变化是缺少 & 来标记指针 .

那么为什么 Scale 改变它收到的变量,即使变量不是指针?

2 回答

  • 8

    游览建议的差异实际上并不是在改变 v := &Vertex{3, 4}v:= Vertex{3, 4} ,而是改变两种方法的定义,以便它们可以处理值而不是指针 . 因此,例如,对于 Scalefunc (v *Vertex) Scale(f float64) {... 变为 func (v Vertex) Scale(f float64) {... (注意 (v *Vertex) ,指针值,变为 (v Vertex) ,非指针值) . 在这两种情况下,您都应将 v 的声明保留为 v := &Vertex{3, 4} .

    您会注意到,在第一种情况下,当方法采用指针时,输出为 &{15 20} 25 . 但是,当方法采用值而不是指针时,输出为 &{3 4} 5 .

    在这两种情况下, v 都是指向 Vertex 对象的指针 . 在第一种情况下,指针被传递给方法,并且一切都按预期工作 - 对 Vertex 对象所做的任何修改都是对原始值进行的,因此这些更改在方法返回后仍然存在 . 在第二种情况下,虽然 v 仍然是一个指针,但Go编译器足够聪明,可以将 v.Scale(5) 转换为 (*v).Scale(5) ,其中 v 被取消引用,结果值传递给 Scale .

  • 1

    它没有"receive"一个值 . Go是强类型的,所以如果在某处指定了指向T的指针,则指向T( *T )的指针是唯一可以作为此类型位置的值发生的选项 .

    "magic"在编译器中有效"rewrites"您的代码在某些conditions下:

    如果方法集(类型)x包含m并且参数列表可以分配给m的参数列表,则方法调用x.m()有效 . 如果x是可寻址的并且&x的方法集包含m,则x.m()是(&x).m()的简写:

    相关:Method sets

相关问题