嵌入类型规则
正确的规则(Go 语言规范)
假设我们有:
type S struct { ... }
func (s S) M1() {} // 值接收者方法
func (s *S) M2() {} // 指针接收者方法
type T struct {
S // 匿名字段 S(值)
// 或者
// *S // 匿名字段 *S(指针)
}
情况1:T 嵌入 S(值)
T的方法集包含S的值接收者方法(即M1,不包括M2)。*T的方法集包含:S的值接收者方法(M1)*S的指针接收者方法(M2)
因为通过
*T可以访问T.S字段,然后可以取地址得到*S,从而调用指针方法。
情况2:T 嵌入 *S(指针)
T的方法集包含S的值接收者方法 和*S的指针接收者方法(即M1和M2都可以)。*T的方法集同样包含S的值方法和*S的指针方法。
因为
T内嵌的是*S,所以T可以直接调用(*S).M2(Go 会自动解引用),同时也拥有S.M1。
您给出的规则分析
- 若类型 T 包含匿名字段 S ,则 T 的方法集包含 S 的方法集
部分正确:只包含 S 的值接收者方法集,不包含 *S 的指针接收者方法。
- 若类型 T 包含匿名字段 S ,则 T 的方法集包含 S 和 S 方法集
这句话重复且无意义,可能是笔误。正确的应该是第二条关于 *T 的规则。
- 不管类型 T 中嵌入的匿名字段是 S 还是 *S ,*T 方法集总是包含 S 和 *S 方法集
正确:是的,*T 总是能获得嵌入类型的所有方法(无论是值接收者还是指针接收者)。
示例验证
type S struct{}
func (S) ValMethod() { println("S.val") }
func (*S) PtrMethod() { println("S.ptr") }
type T1 struct { S } // 嵌入 S(值)
type T2 struct { *S } // 嵌入 *S(指针)
func main() {
// T1 嵌入 S
t1 := T1{S{}}
t1.ValMethod() // ✅ 可以
// t1.PtrMethod() // ❌ 编译错误:T1 没有 PtrMethod
pt1 := &t1
pt1.ValMethod() // ✅ 可以(*T1 提升 S.ValMethod)
pt1.PtrMethod() // ✅ 可以(*T1 提升 *S.PtrMethod)
// T2 嵌入 *S
t2 := T2{&S{}}
t2.ValMethod() // ✅ 可以(通过 *S 调用 S 的方法)
t2.PtrMethod() // ✅ 可以
pt2 := &t2
pt2.ValMethod() // ✅ 可以
pt2.PtrMethod() // ✅ 可以
}
总结
| 嵌入方式 | 类型 T 的方法集 | 类型 *T 的方法集 |
|---|---|---|
T: S | S 的值方法 | S 的值方法 + *S 的指针方法 |
T: *S | S 的值方法 + *S 的指针方法 | S 的值方法 + *S 的指针方法 |
一句话记忆:
- 只有
*T总能获得全部方法(值+指针)。 - 当嵌入的是值
S时,值接收者T只能调用S的值方法;当嵌入的是指针*S时,值接收者T也能调用全部方法。
希望这样解释清楚了。如果您还有其他疑问,欢迎继续提问!