指针接收器方法编译问题:无法在 ‘MyObj{}’ 上调用指针方法。

huangapple go评论62阅读模式
英文:

Pointer receiver method compilation problem: Cannot call a pointer method on 'MyObj{}'

问题

我已经为您翻译了以下内容:

我有以下定义的方法:

func (o *MyObj) parse(something string) string {
    // Do stuff
}

这段代码 (1) 编译通过:

(&MyObj{}).parse(myString)

这段代码 (2) 也编译通过:

m := MyObj{}
m.parse(myString)

但是这段代码 (3) 无法编译通过:

MyObj{}.parse(myString)

出现以下错误:

无法在 'MyObj{}' 上调用指针方法

我的问题:

  1. 为什么 (2) 能够编译通过?我读到过T方法集不包括*T方法集,所以我预期它不会编译通过。

  2. 鉴于 (2) 能够编译通过,为什么 (3) 不能编译通过?

英文:

I have the following method defined:

func (o *MyObj) parse(something string) string {
    // Do stuff
}

This code (1) compiles just fine:

(&MyObj{}).parse(myString)

This code (2) compiles too:

m := MyObj{}
m.parse(myString)

But this code (3) doesn't compile:

MyObj{}.parse(myString)

With the error

> Cannot call a pointer method on 'MyObj{}'

My questions:

  1. Why (2) compiles? I read that T method set doesn't include *T method set, hence I'd expect it not to compile.

  2. Given (2) compiles, why wouldn't (3) compile??

答案1

得分: 4

(2) 中的代码 m.parse(myString) 可以编译通过,因为在它上面调用方法等同于在指针上寻址,然后调用方法,即 (&m).parse(myString)

> 如果 x 是可寻址的,并且 &x 的方法集包含 m,那么 x.m()(&x).m() 的简写形式。

然而,在 (3) 中的 MyObj{}.parse(myString) 中,这种简写形式是不可用的,因为字面量 MyObj{}不可寻址的。根据规范:“地址运算符”

> 操作数必须是可寻址的,即变量、指针间接引用或切片索引操作;[...或其他不适用的情况]。

MyObj{} 是一个复合字面量,它不属于上述任何一种情况;而示例 (2) 中的 m 是一个变量。

最后,关于地址运算符的同一节还指定了一个例外情况,解释了为什么示例 (1) 中的 (&MyObj{}).parse(myString) 可以编译通过:

> 作为对可寻址要求的例外情况,x 也可以是一个(可能带括号的)复合字面量。

在这种情况下,你可以取其地址,加上括号并调用方法,这在语法上类似于编译器对于(2)的简写形式。

英文:

The code in (2) m.parse(myString) compiles because calling the method on it equals to addressing and then calling the method on the pointer, i.e. (&m).parse(myString):

> If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

However this shorthand is not available in (3) MyObj{}.parse(myString) because the literal MyObj{} is not addressable. From the specs: "Address operators":

> The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; [...or other cases that don't apply].

And MyObj{} being a composite literal is neither of those; whereas m from example (2) is a variable.

Finally the same section about address operators specifies an exception that explains why the example in (1) (&MyObj{}).parse(myString) compiles:

> As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

In this case you can take its address, parenthesize it and call the method, which is syntactically similar to the compiler shorthand for (2).

huangapple
  • 本文由 发表于 2021年7月20日 18:24:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/68453300.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定