Pointers 为什么带有指针接收器的方法在接收到值时仍然有效?
我只是在玩。该解释声称Pointers 为什么带有指针接收器的方法在接收到值时仍然有效?,pointers,methods,go,Pointers,Methods,Go,我只是在玩。该解释声称Scale方法在接收到顶点而不是指向顶点的指针时无效 然而,当我在main中将声明v:=&Vertex{3,4}更改为v:=Vertex{3,4}时,输出中唯一的变化就是缺少标记指针的& 那么,为什么即使变量不是指针,Scale也会更改它接收的变量?它不会“接收”值。Go是强类型的,因此如果在某个地方指定了指向T的指针,那么指向T的指针(*T)是唯一可以作为此类类型位置的值出现的选项 “魔力”在于编译器,它在某些情况下有效地“重写”您的代码: 如果方法集x包含m,并且参数列
Scale
方法在接收到顶点而不是指向顶点的指针时无效
然而,当我在main
中将声明v:=&Vertex{3,4}
更改为v:=Vertex{3,4}
时,输出中唯一的变化就是缺少标记指针的&
那么,为什么即使变量不是指针,Scale
也会更改它接收的变量?它不会“接收”值。Go是强类型的,因此如果在某个地方指定了指向T的指针,那么指向T的指针(*T
)是唯一可以作为此类类型位置的值出现的选项
“魔力”在于编译器,它在某些情况下有效地“重写”您的代码:
如果方法集x
包含m
,并且参数列表可以分配给m
的参数列表,则方法调用x.m()
有效。如果x
是可寻址的,并且&x的方法集包含m
,x.m()
是(&x.m()
)的缩写:
相关:本教程所建议的区别实际上并不是将v:=&Vertex{3,4}
更改为v:=Vertex{3,4}
,而是更改这两个方法的定义,以便它们处理值而不是指针。因此,例如,对于Scale
,func(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
,因此,v
在我的情况下不是指针。Scale
可以简单地将其视为一个指针吗?不,Scale
不能将非指针视为指针。答案中的规范摘录解释了Scale
将我将&v
作为它的接收器,而不是v
。好的。但是我可以将指针方法应用于值,就像它们本身就是指针一样。感谢您的解释!考虑到这些值必须是可寻址的。例如,您不能使用文本。