在传统的面向对象编程语言中,继承是一个核心特性,它允许一个类继承另一个类的属性和方法。在 Go 语言中,虽然没有传统意义上的继承机制,但它通过组合(Composition)和接口(Interface)提供了类似的功能。
Go 里 没有 经典意义上的”继承”关键字
在 Go 里,”继承”拆成两件事
- struct 匿名嵌入:复用实现
- interface:抽象多态
把这两个能力拼起来,就能完成传统 OOP
里 90% 的 “继承” 场景。
struct 匿名嵌入
type Animal struct{ Name string }
func (a *Animal) Speak() { fmt.Println("???") }
// Dog “继承” Animal
type Dog struct {
Animal // 没有字段名 -> 匿名嵌入
Breed string
}
- 字段 / 方法提升:
Dog
直接拥有Name
和Speak()
d := Dog{Animal: Animal{Name: "Buddy"}}
d.Speak() // ??? == d.Animal.Speak()
fmt.Println(d.Name) // Buddy == d.Animal.Name
- 方法覆盖:外层再实现同名函数即可覆盖
func (d *Dog) Speak() { fmt.Println("Woof!") } // 优先级更高
底层并无虚表 - 编译器静态把 d.Speak() 展开成 d.Animal.Speak(),调用成本与普通函数一致。
interface 行为多态的唯一机制
type Speaker interface{ Speak() }
func Announce(s Speaker) { s.Speak() }
Announce(&Dog{}) // Dog 满足 Speaker
Announce(&Animal{}) // Animal 也满足
- 隐式实现:只要方法集匹配,无需声明 implements。
- 完全 decouple:调用方只认接口;实现者想怎么组合、怎么嵌入都行。
例子
type Animal struct{ Name string }
func (a *Animal) Speak() { fmt.Println("???") }
type Dog struct{ Animal }
func (d *Dog) Speak() { fmt.Println("Woof!") }
type Speaker interface{ Speak() }
func main() {
var s Speaker = &Dog{Animal: Animal{Name: "Buddy"}}
s.Speak() // Woof! (接口多态)
}