Go 语言完全指南 / 11 - 接口:隐式实现、类型断言、空接口、设计模式
11 - 接口
11.1 接口基础
接口定义了一组方法签名,是 Go 实现多态的核心机制。
package main
import (
"fmt"
"math"
)
// 定义接口
type Shape interface {
Area() float64
Perimeter() float64
}
// Circle 实现 Shape
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
// Rectangle 实现 Shape
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func main() {
var s Shape
s = Circle{Radius: 5}
fmt.Printf("圆形 - 面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
s = Rectangle{Width: 10, Height: 5}
fmt.Printf("矩形 - 面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}
11.2 隐式实现
Go 的接口是隐式实现的——不需要 implements 关键字,只要实现了所有方法就自动满足接口。
// 这就是鸭子类型(Duck Typing)
// "如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"
type Writer interface {
Write(p []byte) (n int, err error)
}
// 任何实现了 Write 方法的类型都自动满足 Writer 接口
type FileWriter struct{ path string }
func (f *FileWriter) Write(p []byte) (int, error) { /*...*/ return len(p), nil }
type Buffer struct{ data []byte }
func (b *Buffer) Write(p []byte) (int, error) { /*...*/ return len(p), nil }
type NetworkWriter struct{ addr string }
func (n *NetworkWriter) Write(p []byte) (int, error) { /*...*/ return len(p), nil }
接口组合
type Reader interface {
Read(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadCloser interface {
Reader
Closer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
11.3 接口作为参数
package main
import "fmt"
type Notifier interface {
Notify(message string)
}
type EmailNotifier struct{ Address string }
func (e EmailNotifier) Notify(msg string) {
fmt.Printf("发送邮件到 %s: %s\n", e.Address, msg)
}
type SMSNotifier struct{ Phone string }
func (s SMSNotifier) Notify(msg string) {
fmt.Printf("发送短信到 %s: %s\n", s.Phone, msg)
}
type SlackNotifier struct{ Channel string }
func (s SlackNotifier) Notify(msg string) {
fmt.Printf("发送 Slack 到 #%s: %s\n", s.Channel, msg)
}
// 函数接受接口参数
func SendAlert(n Notifier, message string) {
n.Notify(message)
}
// 接口切片
func Broadcast(notifiers []Notifier, message string) {
for _, n := range notifiers {
n.Notify(message)
}
}
func main() {
email := EmailNotifier{Address: "[email protected]"}
sms := SMSNotifier{Phone: "+86-13800138000"}
slack := SlackNotifier{Channel: "alerts"}
SendAlert(email, "系统告警!")
SendAlert(sms, "系统告警!")
notifiers := []Notifier{email, sms, slack}
Broadcast(notifiers, "全渠道通知")
}
11.4 空接口 interface
package main
import "fmt"
// interface{} 可以保存任意类型的值
func describe(i interface{}) {
fmt.Printf("类型: %T, 值: %v\n", i, i)
}
// Go 1.18+ 可以用 any(interface{} 的别名)
func describeAny(i any) {
fmt.Printf("类型: %T, 值: %v\n", i, i)
}
func main() {
describe(42)
describe("hello")
describe(3.14)
describe(true)
describe([]int{1, 2, 3})
describe(map[string]int{"a": 1})
// 空接口作为通用容器
var data []any
data = append(data, 42, "hello", 3.14, true)
fmt.Println(data)
}
11.5 类型断言和类型开关
package main
import "fmt"
func process(i any) {
// 类型断言
if s, ok := i.(string); ok {
fmt.Println("字符串:", s)
}
// 类型开关
switch v := i.(type) {
case int:
fmt.Printf("整数: %d\n", v)
case string:
fmt.Printf("字符串: %q\n", v)
case bool:
fmt.Printf("布尔: %v\n", v)
case []int:
fmt.Printf("整数切片: %v\n", v)
case fmt.Stringer:
fmt.Printf("Stringer: %s\n", v.String())
default:
fmt.Printf("未知类型 %T: %v\n", v, v)
}
}
func main() {
process(42)
process("hello")
process(true)
process([]int{1, 2, 3})
// 类型断言的 panic 风险
var i any = "hello"
// s := i.(int) // panic: interface conversion
s, ok := i.(int) // 安全方式
if !ok {
fmt.Println("断言失败")
}
fmt.Println(s, ok)
}
11.6 常用标准库接口
// io 包
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// fmt 包
type Stringer interface {
String() string
}
// sort 包
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
// error 接口
type error interface {
Error() string
}
// http 包
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// 实现 Stringer 接口
type User struct {
Name string
Age int
}
func (u User) String() string {
return fmt.Sprintf("%s (年龄: %d)", u.Name, u.Age)
}
func main() {
u := User{Name: "Alice", Age: 30}
fmt.Println(u) // Alice (年龄: 30)
}
11.7 接口设计模式
依赖注入
// 定义接口
type UserStore interface {
Get(id int) (*User, error)
Save(user *User) error
Delete(id int) error
}
// 服务依赖接口
type UserService struct {
store UserStore
}
func NewUserService(store UserStore) *UserService {
return &UserService{store: store}
}
func (s *UserService) GetUser(id int) (*User, error) {
return s.store.Get(id)
}
// 生产环境实现
type PostgresStore struct {
db *sql.DB
}
func (s *PostgresStore) Get(id int) (*User, error) { /* SQL 查询 */ }
func (s *PostgresStore) Save(user *User) error { /* SQL 插入 */ }
func (s *PostgresStore) Delete(id int) error { /* SQL 删除 */ }
// 测试用 Mock
type MockStore struct {
users map[int]*User
}
func (m *MockStore) Get(id int) (*User, error) { return m.users[id], nil }
func (m *MockStore) Save(user *User) error { m.users[user.ID] = user; return nil }
func (m *MockStore) Delete(id int) error { delete(m.users, id); return nil }
策略模式
type Compressor interface {
Compress(data []byte) ([]byte, error)
}
type GzipCompressor struct{}
func (GzipCompressor) Compress(data []byte) ([]byte, error) { /* gzip */ return data, nil }
type ZlibCompressor struct{}
func (ZlibCompressor) Compress(data []byte) ([]byte, error) { /* zlib */ return data, nil }
type FileProcessor struct {
compressor Compressor
}
func (fp *FileProcessor) Process(filename string) error {
data, _ := os.ReadFile(filename)
compressed, _ := fp.compressor.Compress(data)
return os.WriteFile(filename+".gz", compressed, 0644)
}
中间件模式
type Handler func(http.ResponseWriter, *http.Request)
type Middleware func(Handler) Handler
func Logging(next Handler) Handler {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s", r.Method, r.URL.Path)
next(w, r)
}
}
func Auth(next Handler) Handler {
return func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") == "" {
http.Error(w, "Unauthorized", 401)
return
}
next(w, r)
}
}
func Chain(h Handler, middlewares ...Middleware) Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
h = middlewares[i](h)
}
return h
}
11.8 接口的内部表示
interface{} 内部结构(两个指针):
┌─────────────────┐
│ type pointer ───────→ 类型信息(*rtype)
│ data pointer ───────→ 实际数据
└─────────────────┘
⚠️ 注意:
- 接口值为
nil只有当类型和值都为nil时 - 类型不为
nil的接口值不等于nil
func main() {
var p *int = nil
var i any = p
fmt.Println(i == nil) // false!因为类型信息非 nil
fmt.Println(i) // <nil>
}
🏢 业务场景
- 依赖注入:面向接口编程,方便测试
- 插件系统:定义接口,实现可替换
- 中间件:HTTP、gRPC 中间件链
- 序列化:实现
json.Marshaler、fmt.Stringer等标准接口 - 策略模式:压缩算法、排序策略、日志输出等