首页 > 解决方案 > 结构嵌入提升方法问题中的结构

问题描述

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
}

给我:

$ 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 包含嵌入字段 T,则 S 和 *S 的方法集都包含带有接收者 T 的提升方法。*S 的方法集还包括带有接收者 *T 的提升方法。如果 S 包含嵌入字段 *T,则 S 和 *S 的方法集都包含带有接收器 T 或 *T 的提升方法。

标签: gostructembedding

解决方案


(A) 有效,因为方法调用隐含地获取接收者的地址。

该方法根据问题中引用的提升规则进行提升(*type1).type1Meth2()*type2

关于调用的规范部分说 :

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

该表达式t2.type1Meth2()(&t2).type1Meth2()因为t2是可寻址的并且type1Meth2()在 的方法集中的简写*type2


推荐阅读