当前位置: 首页 > 面试题库 >

“无法获取地址”和“无法调用指针方法”

严柏
2023-03-14
问题内容

可以编译并运行:

diff := projected.Minus(c.Origin)
dir := diff.Normalize()

这不会(产生标题中的错误):

dir := projected.Minus(c.Origin).Normalize()

有人可以帮我理解为什么吗?(学习围棋)

这些是这些方法:

// Minus subtracts another vector from this one
func (a *Vector3) Minus(b Vector3) Vector3 {
    return Vector3{a.X - b.X, a.Y - b.Y, a.Z - b.Z}
}

// Normalize makes the vector of length 1
func (a *Vector3) Normalize() Vector3 {
    d := a.Length()
    return Vector3{a.X / d, a.Y / d, a.Z / d}
}

问题答案:

Vector3.Normalize()方法有一个 指针
接收器,因此要调用此方法,需要一个指向Vector3值的指针(*Vector3)。在第一个示例中,您将的返回值存储Vector3.Minus()在类型为的变量中Vector3

Go中的变量是可寻址的,并且在编写时diff.Normalize(),这是一个快捷方式,编译器将自动获取diff变量的地址,以具有必需的类型的接收者值*Vector3以进行调用Normalize()。因此,编译器会将其“转换”为

(&diff).Normalize()

在“
规范”中对此进行了详细说明:

x.m()如果方法集(的类型)x包含m并且参数列表可以分配给的参数列表,则该方法调用有效m。如果x是可寻址且&x方法集包含mx.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个值,则不应看到明显的性能差异。但是您应该对接收者和结果类型保持一致。如果您的大多数方法都具有指针接收器,那么所有方法都应该具有。如果您的大多数方法都返回指针,那么所有方法也都应返回。



 类似资料:
  • 我正试图遵循这个指南https://aws.amazon.com/blogs/containers/using-alb-ingress-controller-with-amazon-eks-on-fargate/ 步骤如下: 集群资源调配AWS_REGION=us-east-1集群_NAME=eks fargate alb演示 eksctl创建集群--name$cluster\u name--re

  • 我是gccgo新手,我需要编译/运行以下代码的帮助(这在“标准”go编译器中可以正常工作(抱歉,我不知道正确的名称)): 我的gcc: 我的第一个文件: 我的第二个文件: 我的编译错误: 我做错了什么?

  • 问题内容: 当值之一为nil时,我尝试对指向指针的映射进行编码时,Gob的Encode返回错误。这似乎与文档相矛盾(但是我可能会误解其含义): 在切片,数组和映射中,即使所有元素均为零,也会传输所有元素,即使是零值元素。 码: 输出: 在这种情况下,料滴是否有充分的理由失败?似乎两个明显的选择之一都比失败更可取:1)不对任何键值为零的键进行编码,或者2)即使值为零也对所有键进行编码。在当前状态下,

  • 我使用的是jedis版本2.8.0和Spring Data redis版本1.7.5。和redis服务器版本2.8.4。 我有多个缓存得到保存在redis和获取请求是从redis完成的。我正在使用spring data redis API来保存和获取数据。 所有的save和get都可以正常工作,但偶尔geting会低于exception: 我的redis配置类: 有没有人面对过这个问题或者对此有任

  • WooCommerce的顶级页面有商店页、购物车页、结账页、我的账户页和用户协议页,结账页和账户页有次级页面,分别由结账端点和账户端点来指定,也就是endpoints。顶级页面是WordPress里真正的页面,次级页面没有实体页面,只是靠重定向规则动态创造出来的。本文介绍WooCommerce中获取这些页面地址的专用函数。 如何设置WooCommerce顶级页面 一般首次安装时就会提示你设置,如果

  • 我们使用nextjs/reactjs作为FE,并且我们有一个server.js文件,它允许我们在上传映像,但是由于某种原因,每当我们运行服务器时,都会出现错误 下面是我们在server.js上的代码 这些是我们package.json中包含的脚本 希望得到一些答案和建议。这些代码在本地运行,没有任何问题