来自Go规范的调用部分:https://golang.org/ref/spec#Calls
如果方法集{(1)}的
的简写x.m()
包含x
并且参数列表可以分配给{{1}的参数列表,则方法调用m
有效}。如果m
可寻址并且x
的方法集包含&x
,则m
是x.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
,则m
是x.m()
我的问题。
(&x).m()
?我的猜测是"否"因为虽然p.FakeScale(10)
是可寻址的,但p
的方法集不包含&p
。 FakeScale
的方法集包含p
,因为它使用值接收器,但FakeScale
的方法集不包含p
,因此这部分该规范不适用于FakeScale
。我是对的吗?p.FakeScale(10)
?我猜是"是"因为p.RealScale(10)
是可寻址的,并且p
的方法集包含&p
,因为它使用指针接收器。因此,此部分规范适用于RealScale
。我是对的吗?p.RealScale(10)
有效但x.m()
不可寻址的示例代码,因此该部分规范不适用?答案 0 :(得分:0)
不幸的是,语言律师必须阅读整个规范,将一句话放在上下文中:The Go Programming Language Specification。
类型可能具有与之关联的方法集。方法集 接口类型是它的接口。任何其他类型T的方法集 由接收器类型T声明的所有方法组成。方法集 对应的指针类型* T是所有方法的集合 用接收器* T或T声明(也就是说,它也包含方法 一套T)。进一步的规则适用于包含匿名字段的结构, 如结构类型一节中所述。任何其他类型都有 空方法集。在方法集中,每个方法必须具有唯一性 非空方法名称。
类型的方法集确定类型的接口 实现和可以使用接收器调用的方法 类型。
方法调用x.m()在方法集(类型)x时有效 包含m,参数列表可以分配给参数列表 米如果x是可寻址的并且& x的方法集包含m,则x.m()是 (& x).m()的简写。
对于类型为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)
嗯。我也开始怀疑自己对英语的了解,但我会尽力回答。
你从规范中引用了两句话。
回到你的问题:
您为 2种类型定义了2种方法:第一种 - 接收Point和第二种 - 指向Point的接收器。
显然,指针类型的简写定义不适用于非指针类型。
所以,你在问题1或2中是正确的。
你的第三个问题实际上是问题1:FakeScale是有效的方法,但在接收器中使用非指针类型的方法,因此速记定义不适用。