Go 方法调用速记规范适用性

标签 go methods specifications

来自 Go 规范的调用部分:https://golang.org/ref/spec#Calls

A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

我的程序。

package main

import (
    "fmt"
)

func main() {
    p := Point{2, 3}

    p.FakeScale(10)
    fmt.Println(p)

    p.RealScale(10)
    fmt.Println(p)
}

type Point struct {
    x int
    y int
}

func (p Point) FakeScale(s int) {
    p.x *= s
    p.y *= s
}

func (p *Point) RealScale(s int) {
    p.x *= s
    p.y *= s
}

这是输出。

{2, 3}
{20, 30}

我的问题专门针对规范的这一部分。

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

我的问题。

  1. 引用的部分是否适用于 p.FakeScale(10)?我的猜测是“否”,因为虽然 p 是可寻址的,但 &p 的方法集不包含 FakeScalep的方法集包含FakeScale,因为它使用了值接收器,但是p的方法集不包含FakeScale,因此这部分规范不适用于 p.FakeScale(10)。我说得对吗?
  2. 引用的部分是否适用于 p.RealScale(10)?我的猜测是"is",因为 p 是可寻址的,并且 &p 的方法集由于使用指针接收器而包含 RealScale。因此,这部分规范适用于 p.RealScale(10)。我说得对吗?
  3. 您能否提供一个示例代码,其中 x.m() 有效但 x 不可寻址,因此这部分规范不适用?

最佳答案

不幸的是,语言律师必须阅读整个规范才能将单个句子放在上下文中:The Go Programming Language Specification .

Method sets

A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing anonymous fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.

The method set of a type determines the interfaces that the type implements and the methods that can be called using a receiver of that type.

Calls

A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

Address operators

For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.


例如,

package main

import (
    "fmt"
)

type Point struct {
    x int
    y int
}

func (p Point) FakeScale(s int) {
    p.x *= s
    p.y *= s
}

func (p *Point) RealScale(s int) {
    p.x *= s
    p.y *= s
}

func main() {
    p := Point{2, 3}

    p.FakeScale(10)
    fmt.Println(p)

    p.RealScale(10)
    fmt.Println(p)
}

Point 类型的方法集由所有声明为接收者类型 Point (FakeScale) 的方法组成。

方法调用 p.FakeScale 是有效的,因为 p (Point) 的(类型)的方法集包含 FakeScale 并且参数列表 (10) 可以分配给 FakeScale 的参数列表 (int) .

*Point 类型的方法集包含所有声明为 *Point (RealScale) 接收者类型的方法。

由于 p 是可寻址的(p 是一个变量)并且 &p 的方法集包含 RealScale,因此 p.RealScale() 是 (&p).RealScale() 的简写。


另外,请参阅我对您先前问题的回答:How to invoke a method with pointer receiver after type assertion? .

关于Go 方法调用速记规范适用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43953187/

相关文章:

java - 从方法返回一个值并将其存储到数组中以供另一个方法使用

javascript - var functionName = function() {} vs function functionName() {}

javascript - ES2015函数名推断在哪里定义的?

uml - Action 执行规范和行为执行规范

rpmbuild - 如果 SPEC 文件的 %Files 部分中的条件

c++ - 如何在Cgo中使用GoMap?

rest - 从客户端向服务器发送数据 - REST webservice

go - 如何初始化嵌套的复杂结构

http - 在超时处理程序中进入竞争条件

flash - 在 AS3 方法中接受多个参数