Go 没有类继承,通过匿名字段(嵌入)实现代码复用:外层结构体自动获得嵌入类型的字段和方法(提升机制),并满足嵌入类型实现的接口。这本质仍是组合——嵌入字段有一个隐含字段名(类型名),方法提升只是编译器的转发语法糖,不存在虚函数表和父子类型层级。
与继承的关键区别:嵌入类型不知道外层类型的存在,其方法内部调用自己的方法不会动态分派到外层'重写'的版本,没有 OOP 的多态陷阱;字段或方法名冲突时浅层覆盖深层,同深度冲突则引用时编译报错,行为可预测。
type Logger struct{ prefix string }
func (l Logger) Log(msg string) { fmt.Println(l.prefix, msg) }
type Server struct {
Logger // 嵌入
addr string
}
s := Server{Logger: Logger{prefix: "srv"}}
s.Log("started") // 提升调用,等价 s.Logger.Log(...)
易错点:嵌入指针类型时注意 nil 解引用 panic;JSON 序列化时嵌入字段会平铺展开。追问方向:接口嵌入(如 io.ReadWriter)、用嵌入做 mock 和中间件包装。