Go中适配器模式天然契合接口与组合机制,只需定义目标接口、包装旧类型或函数即可;常见陷阱包括嵌入不自动实现接口、接收器类型不匹配、函数赋值错误及泛型滥用。

Go 里实现适配器模式,根本不需要“学语言”再动手——它天然就长在 Go 的接口和组合机制里。只要你定义了目标接口、有不匹配的旧类型(或函数)、再写个薄层包装,适配就完成了。关键不是语法多难,而是别掉进嵌入误判、方法接收器错配、泛型滥用这些坑。
为什么嵌入 struct 后还报 “does not implement xxx”
嵌入只是字段复用,不是自动实现接口。编译器只看方法集是否完整,不管有没有 embed 关键字或匿名字段。
- 常见错误:嵌入的是值类型
Adaptee,但目标接口方法是 *Adaptee 上定义的指针接收器 - 另一个坑:被适配者方法用值接收器,你却用指针嵌入,导致方法集不匹配
- 函数类型适配时,忘记把函数赋给结构体字段,或调用时没传参
- 泛型适配器里类型约束写错,比如用了
any却期望有特定方法
用结构体嵌套适配第三方日志库
假设你要把 log.Printf 塞进自定义的 Logger 接口,最简方式就是封装一个结构体:
type Logger interface {
Info(msg string)
Error(msg string)
}
type StdLoggerAdapter struct {
logFunc func(string, ...interface{})
}
func (a *StdLoggerAdapter) Info(msg string) {
a.logFunc("[INFO] %s", msg)
}
func (a *StdLoggerAdapter) Error(msg string) {
a.logFunc("[ERROR] %s", msg)
}
// 使用
adapter := &StdLoggerAdapter{logFunc: log.Printf}
注意:logFunc 字段必须是函数类型,不能是 log.Logger 实例;调用时参数要对齐,否则运行时报 panic。
立即学习“go语言免费学习笔记(深入)”;
用函数类型直接适配 HTTP Handler
Go 的 http.HandlerFunc 本身就是个经典适配器:它把普通函数转成满足 http.Handler 接口的类型。
- 你写的
func(w http.ResponseWriter, r *http.Request)本身不实现http.Handler - 但包一层
http.HandlerFunc(yourFunc)就自动有了ServeHTTP方法 - 自己仿写也简单:
type MyHandler func(http.ResponseWriter, *http.Request),再为它实现ServeHTTP - 这种函数类型适配比结构体更轻量,适合无状态、单方法场景
泛型适配器容易忽略的约束边界
泛型不是万能胶,用不好反而让适配器变重、难读、难测。
- 别一上来就套
type Adapter[T any]——如果只适配一种类型,泛型纯属增加认知负担 - 约束要具体:
type Adapter[T interface{ Do() string }]比T any更安全、更易推导 - 泛型适配器里嵌入原类型时,注意是否支持值/指针接收器混合使用
- 生成的代码体积会随实例化类型增多而膨胀,生产环境慎用于高频小对象
真正该花时间琢磨的,不是怎么写泛型,而是判断这个适配器是否真需要跨多种类型复用——大多数时候,一个干净的结构体 + 明确字段,已经够用且稳定。


















