Go 语言通过接口(interface)提供了一种灵活的多态机制,允许我们以抽象方式编程,提高代码的可扩展性与可测试性。
一、接口的定义
接口是一组方法的集合,任何类型只要实现了接口中定义的所有方法,就被认为“实现了该接口”,无需显式声明。
示例:
type Speaker interface {
Speak() string
}
定义了一个名为 Speaker 的接口,要求实现 Speak() 方法。
二、接口的实现
Go 的类型通过“方法集匹配”隐式实现接口。
type Person struct {
Name string
}
func (p Person) Speak() string {
return "Hi, I'm " + p.Name
}
此时 Person 类型已经自动实现了 Speaker 接口:
var s Speaker
s = Person{Name: "Alice"}
fmt.Println(s.Speak()) // 输出:Hi, I'm Alice
✅ 不需要类似 implements 的显式关键词。
三、多种类型实现同一接口
type Dog struct{}
func (d Dog) Speak() string {
return "Woof!"
}
type Cat struct{}
func (c Cat) Speak() string {
return "Meow!"
}
func SaySomething(s Speaker) {
fmt.Println(s.Speak())
}
调用:
SaySomething(Dog{}) // Woof!
SaySomething(Cat{}) // Meow!
四、空接口 interface{}
空接口没有任何方法,是所有类型的“超类型”。
var x interface{}
x = 42
x = "hello"
通常用于接收任意类型的值,例如:
func PrintAnything(a interface{}) {
fmt.Println(a)
}
五、类型断言
将空接口还原为具体类型:
var i interface{} = "hello"
s := i.(string) // 断言成功
fmt.Println(s)
v, ok := i.(int) // 断言失败不会 panic
fmt.Println(ok) // false
六、接口组合
接口之间可以嵌套组合:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
ReadWriter 包含了 Reader 和 Writer 的所有方法。
七、接口与 nil
接口类型变量的 nil 判断容易出错:
var s Speaker // 接口值为 nil
fmt.Println(s == nil) // true
var p *Person = nil
var i Speaker = p
fmt.Println(i == nil) // false!因为接口不为 nil(动态类型不为 nil)
🧠 接口为 nil = 类型和值都为 nil。
八、接口应用场景
- • 依赖注入和测试模拟
- • 定义规范:如
io.Reader、http.Handler - • 多态调用:根据不同实现执行不同逻辑
九、小结
| 概念 | 描述 |
|---|---|
| 接口定义 | 仅定义方法签名,不包含实现 |
| 实现方式 | 隐式实现,自动匹配方法集 |
| 空接口 | 接收任意类型(interface{}) |
| 类型断言 | 将接口还原为具体类型(v := x.(T)) |
| 接口组合 | 支持接口嵌套,便于功能拆分与组合 |