Skip to main content

嵌入类型规则


正确的规则(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 的指针接收者方法(即 M1M2 都可以)。
  • *T 的方法集同样包含 S 的值方法和 *S 的指针方法。

因为 T 内嵌的是 *S,所以 T 可以直接调用 (*S).M2(Go 会自动解引用),同时也拥有 S.M1


您给出的规则分析

  1. 若类型 T 包含匿名字段 S ,则 T 的方法集包含 S 的方法集

部分正确:只包含 S值接收者方法集,不包含 *S 的指针接收者方法。

  1. 若类型 T 包含匿名字段 S ,则 T 的方法集包含 S 和 S 方法集

这句话重复且无意义,可能是笔误。正确的应该是第二条关于 *T 的规则。

  1. 不管类型 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: SS 的值方法S 的值方法 + *S 的指针方法
T: *SS 的值方法 + *S 的指针方法S 的值方法 + *S 的指针方法

一句话记忆

  • 只有 *T 总能获得全部方法(值+指针)。
  • 当嵌入的是S 时,值接收者 T 只能调用 S 的值方法;当嵌入的是指针 *S 时,值接收者 T 也能调用全部方法。

希望这样解释清楚了。如果您还有其他疑问,欢迎继续提问!