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
。好的。但是我可以将指针方法应用于值,就像它们本身就是指针一样。感谢您的解释!考虑到这些值必须是可寻址的。例如,您不能使用文本。