英文:
Struct in struct embedding promoted methods question
问题
package main
import "fmt"
type type1 struct { //T
}
func (t1 type1) type1Meth1() {
fmt.Printf("===> func (t1 type1) type1Meth1():\n Type: %T\n Value: %+v\n\n", t1, t1)
}
func (t1 *type1) type1Meth2() {
fmt.Printf("===> func (t1 *type1) type1Meth2():\n Type: %T\n Value: %p\n Contains: %+v\n\n", t1, t1, t1)
}
func (t1 type1) type1Meth3() {
fmt.Printf("===> func (t1 type1) type1Meth3():\n Type: %T\n Value: %+v\n", t1, t1)
}
type type2 struct { //S
type1
}
func (t2 *type2) type1Meth3() {
fmt.Printf("===> func (t2 *type2) type1Meth3(): Type: %T\n Value: %+v\n\n", t2, t2)
}
func main() {
t2 := type2{}
t2.type1Meth1() // type2包含type1的方法集
t2.type1Meth2() // 不确定为什么这个可以工作?type2没有*type1的方法集(A)
t2.type1Meth3() // type2包含type1的方法集。通过嵌入类型type2截取并使用*type2接收器调用
}
输出结果:
$ go run embed-struct-in-struct.go
===> func (t1 type1) type1Meth1():
Type: main.type1
Value: {}
===> func (t1 *type1) type1Meth2():
Type: *main.type1
Value: 0x116be80
Contains: &{}
===> func (t2 *type2) type1Meth3(): Type: *main.type2
Value: &{type1:{}}
go version
go version go1.17.2 darwin/amd64
不确定为什么在(A)中的调用可以工作?
文档中说明:嵌入方法将按照以下方式包含在结构体的方法集中:
-
如果S包含一个嵌入字段T,则S和*S的方法集都包括具有接收器T的嵌入方法。S的方法集还包括具有接收器T的嵌入方法。
-
如果S包含一个嵌入字段T,则S和S的方法集都包括具有接收器T或*T的嵌入方法。
英文:
package main
import "fmt"
type type1 struct { //T
}
func (t1 type1) type1Meth1() {
fmt.Printf("==> func (t1 type1) type1Meth1():\n Type: %T\n Value: %+v\n\n", t1, t1)
}
func (t1 *type1) type1Meth2() {
fmt.Printf("==> func (t1 *type1) type1Meth2():\n Type: %T\n Value: %p\n Contains: %+v\n\n", t1, t1, t1)
}
func (t1 type1) type1Meth3() {
fmt.Printf("==> func (t1 type1) type1Meth3():\n Type: %T\n Value: %+v\n", t1, t1)
}
type type2 struct { //S
type1
}
func (t2 *type2) type1Meth3() {
fmt.Printf("==> func (t2 *type2) type1Meth3(): Type: %T\n Value: %+v\n\n", t2, t2)
}
func main() {
t2 := type2{}
t2.type1Meth1() // type2 contains method set of type1
t2.type1Meth2() // not sure, why this works? type2 does not have method set of *type1 (A)
t2.type1Meth3() // type2 contains method set of type1. intercepted by embedding type type2 and called with *type2 receiver
}
Gives me:
$ go run embed-struct-in-struct.go
==> func (t1 type1) type1Meth1():
Type: main.type1
Value: {}
==> func (t1 *type1) type1Meth2():
Type: *main.type1
Value: 0x116be80
Contains: &{}
==> func (t2 *type2) type1Meth3(): Type: *main.type2
Value: &{type1:{}}
go version
go version go1.17.2 darwin/amd64
Not sure why call in (A) works?
Documentation says: promoted methods are included in the method set of the struct as follows:
> Given a struct type S and a defined type T, promoted methods are included in the method set of the struct as follows:
> If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
> If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
答案1
得分: 3
(A)之所以有效,是因为方法调用隐式地获取了接收者的地址。
根据问题中引用的提升规则,方法(*type1).type1Meth2()
被提升为*type2
。
在规范的调用部分中有这样的说明:
> 如果方法集(的类型)x包含m,并且参数列表可以分配给m的参数列表,则方法调用x.m()是有效的。如果x是可寻址的,并且&x的方法集包含m,则x.m()是(&x).m()的简写形式:
表达式t2.type1Meth2()
是(&t2).type1Meth2()
的简写形式,因为t2
是可寻址的,并且type1Meth2()
在*type2
的方法集中。
英文:
(A) works because the method call implicitly takes the address of the receiver.
The method (*type1).type1Meth2()
is promoted to *type2
per the promotion rules quoted in the question.
The section of the specification on calls says:
> 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():
The expression t2.type1Meth2()
is shorthand for (&t2).type1Meth2()
because t2
is addressable and type1Meth2()
is in the method set of *type2
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论