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

时间:2017-05-13 12:31:00

标签: go methods specifications

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

  

如果方法集{(1)}的x.m()包含x并且参数列表可以分配给{{1}的参数列表,则方法调用m有效}。如果m可寻址并且x的方法集包含&x,则mx.m()

的简写

我的节目。

(&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} 可寻址且x的方法集包含&x,则mx.m()

的简写

我的问题。

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

2 个答案:

答案 0 :(得分:0)

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

  

Method sets

     

类型可能具有与之关联的方法集。方法集   接口类型是它的接口。任何其他类型T的方法集   由接收器类型T声明的所有方法组成。方法集   对应的指针类型* T是所有方法的集合   用接收器* T或T声明(也就是说,它也包含方法   一套T)。进一步的规则适用于包含匿名字段的结构,   如结构类型一节中所述。任何其他类型都有   空方法集。在方法集中,每个方法必须具有唯一性   非空方法名称。

     

类型的方法集确定类型的接口   实现和可以使用接收器调用的方法   类型。

     

Calls

     

方法调用x.m()在方法集(类型)x时有效   包含m,参数列表可以分配给参数列表   米如果x是可寻址的并且& x的方法集包含m,则x.m()是   (& x).m()的简写。

     

Address operators

     

对于类型为T的操作数x,地址操作& x生成a   类型* T到x的指针。操作数必须是可寻址的,即   变量,指针间接或切片索引操作;   或可寻址结构操作数的字段选择器;或数组   可寻址数组的索引操作。作为例外   可寻址性要求,x也可以是(可能括在括号中)   复合文字。

例如,

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?

答案 1 :(得分:-2)

嗯。我也开始怀疑自己对英语的了解,但我会尽力回答。

你从规范中引用了两句话。

  1. 描述方法有效的条件。
  2. 描述指针类型接收者的简写。
  3. 回到你的问题:

    您为 2种类型定义了2种方法:第一种 - 接收Point和第二种 - 指向Point的接收器。

    显然,指针类型的简写定义不适用于非指针类型。

    所以,你在问题1或2中是正确的。

    你的第三个问题实际上是问题1:FakeScale是有效的方法,但在接收器中使用非指针类型的方法,因此速记定义不适用。