该
Vector3.Normalize()方法有一个 指针
接收器,因此要调用此方法,需要一个指向
Vector3值的指针(
*Vector3)。在第一个示例中,您将的返回值存储
Vector3.Minus()在类型为的变量中
Vector3。
Go中的变量是可寻址的,并且在编写时
diff.Normalize(),这是一个快捷方式,编译器将自动获取
diff变量的地址,以具有必需的类型的接收者值
*Vector3以进行调用
Normalize()。因此,编译器会将其“转换”为
(&diff).Normalize()
在“
规范”中对此进行了详细说明:
x.m()如果方法集(的类型)x包含m并且参数列表可以分配给的参数列表,则该方法调用有效m。如果x是可寻址且&x方法集包含m,x.m()则为的简写(&x).m()。
您的第二个示例不起作用的原因是因为函数和方法调用的返回值 不可寻址
,因此编译器在此处无法执行同样的操作,编译器无法采用该函数的返回值的地址。
Vector3.Minus()呼叫。
在“
规范:地址”运算符中准确列出了可寻址的内容:
操作数必须是 可寻址的 ,即变量,指针间接 寻址
或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。作为可寻址性要求的例外,x[在表达式中&x]也可以是(可能带有括号的)复合文字。
可能的“解决方法”
“最简单”(需要最少的更改)只是分配给变量,然后在此之后调用方法。这是您的第一个可行的解决方案。
另一种方法是将方法修改为具有值接收器(而不是指针接收器),从而无需获取方法返回值的地址,因此可以将调用“链接”。请注意,如果某个方法需要修改接收方,则这可能不可行,因为只有当它是指针时才可能这样做(因为接收方就像通过传递副本一样通过任何其他参数传递,并且如果它不是指针,则被传递,则只能修改副本)。
另一种方法是将返回值修改为返回指针(
*Vector3)而不是
Vector3。如果返回值已经是一个指针,则不需要使用它的地址,因为对于需要接收者的方法来说,接收器的状态是良好的。
您也可以创建一个简单的帮助函数,该函数返回其地址。它可能看起来像这样:
func pv(v Vector3) *Vector3 { return &v}使用它:
dir := pv(projected.Minus(c.Origin)).Normalize()
这也可以是的方法
Vector3,例如:
func (v Vector3) pv() *Vector3 { return &v}然后使用它:
dir := projected.Minus(c.Origin).pv().Normalize()
一些注意事项:
如果您的类型
float64仅包含3个值,则不应看到明显的性能差异。但是您应该对接收者和结果类型保持一致。如果您的大多数方法都具有指针接收器,那么所有方法都应该具有。如果您的大多数方法都返回指针,那么所有方法也都应返回。



