全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-14 7 分钟 ✍️ juanwangdev

Go接口与多态

Go通过接口实现多态,不同类型可实现相同接口表现出不同行为。

多态基本概念

定义接口

Go
type Animal interface {
    Speak() string
}

// 不同类型实现同一接口
type Dog struct{}
func (d Dog) Speak() string { return "汪汪" }

type Cat struct{}
func (c Cat) Speak() string { return "喵喵" }

type Cow struct{}
func (c Cow) Speak() string { return "哞哞" }

多态调用

Go
func makeSound(a Animal) {
    fmt.Println(a.Speak())
}

func main() {
    makeSound(Dog{})  // 汪汪
    makeSound(Cat{})  // 喵喵
    makeSound(Cow{})  // 哞哞
}

同一函数接受不同类型,表现出不同行为。

接口赋值

值类型赋值

Go
var a Animal = Dog{}  // 值赋值
a.Speak()  // "汪汪"

// Dog{}满足Animal接口

指针类型赋值

Go
var a Animal = &Dog{}  // 指针赋值
a.Speak()  // "汪汪"

// *Dog也满足Animal接口

接口变量存储

Go
var animals []Animal
animals = append(animals, Dog{})
animals = append(animals, Cat{})
animals = append(animals, &Cow{})

for _, a := range animals {
    fmt.Println(a.Speak())
}

动态调用原理

接口内部结构

Go
// 接口包含类型信息和数据指针
type iface struct {
    tab  *itab   // 接口表(包含方法地址)
    data unsafe.Pointer  // 数据指针
}

// 方法调用时:
// 1. 从itab查找方法地址
// 2. 调用具体类型的实现

动态调用示例

Go
var a Animal

a = Dog{}
a.Speak()  // 调用Dog.Speak

a = Cat{}
a.Speak()  // 调用Cat.Speak

// 编译时不知道具体类型
// 运行时动态查找方法

多态应用场景

策略模式

Go
type Sorter interface {
    Sort([]int) []int
}

type QuickSort struct{}
func (q QuickSort) Sort(data []int) []int {
    // 快速排序实现
    return data
}

type BubbleSort struct{}
func (b BubbleSort) Sort(data []int) []int {
    // 冒泡排序实现
    return data
}

func sortData(data []int, sorter Sorter) []int {
    return sorter.Sort(data)
}

插件模式

Go
type Plugin interface {
    Name() string
    Execute(input string) string
}

func runPlugin(p Plugin, input string) {
    fmt.Println("执行:", p.Name())
    output := p.Execute(input)
    fmt.Println("结果:", output)
}

Mock测试

Go
type Repository interface {
    Find(id int) (*User, error)
    Save(user *User) error
}

// 真实实现
type MySQLRepo struct{}

// Mock实现(测试)
type MockRepo struct{}
func (m MockRepo) Find(id int) (*User, error) {
    return &User{Name: "Mock"}, nil
}

// 测试时使用Mock
func TestService(t *testing.T) {
    repo := MockRepo{}
    service := NewService(repo)
    // 测试逻辑...
}

多态优势

优势说明
解耦调用者不依赖具体类型
扩展新类型满足接口即可
测试Mock实现替代真实类型
简洁统一接口简化调用

多态注意事项

方法必须完全匹配

Go
type Reader interface {
    Read(p []byte) (int, error)
}

// 方法签名必须完全一致
type MyReader struct{}
func (m MyReader) Read(p []byte) (int, error) {
    return len(p), nil
}

// 以下不满足Reader接口
func (m MyReader) Read(p []byte) int {
    return len(p)  // 返回值不匹配
}

空接口与多态

Go
// 空接口接受任何类型
var i interface{} = Dog{}
var j interface{} = 42

// 但无法调用方法(空接口无方法)
// i.Speak()  // 编译错误

要点总结

  • 接口实现多态,不同类型相同行为
  • 值类型和指针类型都可赋给接口
  • 方法签名必须完全匹配接口
  • 接口变量存储类型信息和数据指针
  • 动态调用在运行时查找方法地址
  • 多态用于策略模式、插件、Mock测试
  • 新类型满足接口即可扩展,无需修改调用者

📝 发现内容有误?点击此处直接编辑

← 上一篇 Go值接收者与指针接收者
下一篇 → Go接口定义与实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库