跳到主要内容

适配器模式

问题

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.NopCloserio.Readerio.ReadCloser
strings.NewReaderstringio.Reader
bytes.NewBuffer[]byteio.ReadWriter

常见面试问题

Q1: http.HandlerFunc 为什么被称为适配器?

答案:它解决的问题是接口不匹配

  • http.Handle 需要 Handler 接口(有 ServeHTTP 方法的类型)
  • 但写一个函数比定义一个结构体方便
  • HandlerFunc 是函数类型,实现了 Handler 接口,将函数"适配"成接口
// 类型转换即适配
http.HandlerFunc(myFunc) // myFunc 函数 → Handler 接口

相关链接