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) ) |
接口组合 | 支持接口嵌套,便于功能拆分与组合 |