Appearance
第 12 章:接口(Go 核心特性)
12.1 什么是接口?接口的作用
接口是一种抽象类型,它定义了一组方法签名,而不实现这些方法。接口的主要作用是:
- 实现多态
- 解耦代码
- 提高代码的可测试性和可扩展性
12.2 接口定义与实现(非侵入式)
接口定义
go
type Animal interface {
Speak() string
Move() string
}接口实现
在 Go 中,接口的实现是隐式的,不需要显式声明。只要一个类型实现了接口的所有方法,它就自动实现了该接口:
go
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return "Woof!"
}
func (d Dog) Move() string {
return "Run"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return "Meow!"
}
func (c Cat) Move() string {
return "Walk"
}使用接口
go
func makeAnimalSpeak(a Animal) {
fmt.Println(a.Speak())
}
func main() {
dog := Dog{Name: "Rex"}
cat := Cat{Name: "Whiskers"}
makeAnimalSpeak(dog) // 输出 Woof!
makeAnimalSpeak(cat) // 输出 Meow!
}12.3 空接口 interface {}
空接口没有任何方法,因此所有类型都实现了空接口:
go
var i interface{}
// 可以存储任何类型的值
i = 42
fmt.Println(i)
i = "hello"
fmt.Println(i)
i = Dog{Name: "Rex"}
fmt.Println(i)空接口的应用
- 作为函数参数,接收任意类型
- 作为 map 的值类型,存储不同类型的值
- 作为 slice 的元素类型,存储不同类型的值
12.4 类型断言
类型断言用于将接口类型转换为具体类型:
基本用法
go
var i interface{} = 42
// 类型断言
v, ok := i.(int)
if ok {
fmt.Println("i is an int:", v)
} else {
fmt.Println("i is not an int")
}类型断言与 switch
go
func process(i interface{}) {
switch v := i.(type) {
case int:
fmt.Println("Integer:", v)
case string:
fmt.Println("String:", v)
case bool:
fmt.Println("Boolean:", v)
default:
fmt.Println("Unknown type")
}
}
func main() {
process(42)
process("hello")
process(true)
process(Dog{Name: "Rex"})
}12.5 接口实战:多态实现
案例 1:形状接口
go
package main
import "fmt"
type Shape interface {
Area() float64
Perimeter() float64
}
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
func printShapeInfo(s Shape) {
fmt.Printf("Area: %.2f\n", s.Area())
fmt.Printf("Perimeter: %.2f\n", s.Perimeter())
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
circle := Circle{Radius: 7}
fmt.Println("Rectangle:")
printShapeInfo(rect)
fmt.Println("\nCircle:")
printShapeInfo(circle)
}案例 2:工作接口
go
package main
import "fmt"
type Worker interface {
Work() string
Rest() string
}
type Engineer struct {
Name string
}
func (e Engineer) Work() string {
return e.Name + " is coding"
}
func (e Engineer) Rest() string {
return e.Name + " is taking a break"
}
type Teacher struct {
Name string
}
func (t Teacher) Work() string {
return t.Name + " is teaching"
}
func (t Teacher) Rest() string {
return t.Name + " is drinking coffee"
}
func simulateDay(w Worker) {
fmt.Println(w.Work())
fmt.Println(w.Rest())
}
func main() {
engineer := Engineer{Name: "Alice"}
teacher := Teacher{Name: "Bob"}
fmt.Println("Engineer's day:")
simulateDay(engineer)
fmt.Println("\nTeacher's day:")
simulateDay(teacher)
}