适配器模式
问题
Go 中如何实现适配器模式?
答案
函数适配器
Go 标准库中最经典的适配器:http.HandlerFunc。
// http.Handler 接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// http.HandlerFunc 适配器:把普通函数适配成 Handler 接口
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
// 使用:普通函数 → Handler 接口
func hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
}
mux.Handle("/hello", http.HandlerFunc(hello)) // 函数适配为接口
接口适配器
// 旧接口
type OldLogger interface {
LogMessage(level int, msg string)
}
// 新接口
type Logger interface {
Info(msg string)
Error(msg string)
}
// 适配器:让旧实现适配新接口
type LoggerAdapter struct {
old OldLogger
}
func (a *LoggerAdapter) Info(msg string) { a.old.LogMessage(1, msg) }
func (a *LoggerAdapter) Error(msg string) { a.old.LogMessage(3, msg) }
// 使用
var newLogger Logger = &LoggerAdapter{old: legacyLogger}
标准库中的适配器
| 适配器 | 作用 |
|---|---|
http.HandlerFunc | 函数 → http.Handler |
sort.Reverse | 反转排序 |
io.NopCloser | io.Reader → io.ReadCloser |
strings.NewReader | string → io.Reader |
bytes.NewBuffer | []byte → io.ReadWriter |
常见面试问题
Q1: http.HandlerFunc 为什么被称为适配器?
答案:它解决的问题是接口不匹配:
http.Handle需要Handler接口(有ServeHTTP方法的类型)- 但写一个函数比定义一个结构体方便
HandlerFunc是函数类型,实现了Handler接口,将函数"适配"成接口
// 类型转换即适配
http.HandlerFunc(myFunc) // myFunc 函数 → Handler 接口