适配器模式在Go中通过组合和接口隐式实现,以桥接不兼容接口;例如用LegacyLoggerAdapter包装LegacyLogger并实现Logger接口,或用EmailWriter将sendEmail函数适配为Writer接口。

适配器模式的核心是让两个不兼容的接口能一起工作——Golang 没有继承,但通过组合和接口隐式实现,实现起来更轻量、更自然。
理解适配目标:定义“旧接口”与“新需求”
先明确谁需要被适配、谁是调用方。例如:
- 已有类型
LegacyLogger只有LogError(msg string)方法; - 但新业务代码依赖统一的
Logger接口:Log(level string, msg string)。
二者方法签名不匹配,无法直接传入。这时就需要一个适配器桥接。
用结构体组合 + 接口实现完成适配
Golang 中最常用的方式是定义一个新结构体,内嵌旧类型,并实现目标接口:
立即学习“go语言免费学习笔记(深入)”;
type LegacyLogger struct{}
func (l *LegacyLogger) LogError(msg string) {
fmt.Println("[ERROR]", msg)
}
// 目标接口
type Logger interface {
Log(level string, msg string)
}
// 适配器:包装 LegacyLogger,实现 Logger 接口
type LegacyLoggerAdapter struct {
*LegacyLogger // 组合复用
}
func (a *LegacyLoggerAdapter) Log(level string, msg string) {
if level == "error" {
a.LogError(msg) // 转发到原有逻辑
} else {
fmt.Printf("[%s] %s\n", strings.ToUpper(level), msg)
}
}
调用时只需传入 &LegacyLoggerAdapter{&LegacyLogger{}},即可满足 Logger 类型要求。
函数适配器:适合简单场景或第三方库
若旧能力是函数(如 func(string) error),而你需要它满足某个接口,可封装为闭包或适配函数:
type Writer interface {
Write([]byte) (int, error)
}
// 第三方函数:func(string) error
func sendEmail(content string) error { / ... / }
// 函数适配器:转成 Writer
type EmailWriter struct {
sendFunc func(string) error
}
func (e *EmailWriter) Write(p []byte) (int, error) {
err := e.sendFunc(string(p))
return len(p), err
}
// 使用
writer := &EmailWriter{sendEmail}
io.WriteString(writer, "Hello from adapter!")
避免常见陷阱
- 不要暴露被适配类型的原始方法:适配器应只提供目标接口契约,避免调用方误用内部旧方法;
- 适配器应无状态或轻量:它只是转发层,不建议在其中维护复杂逻辑或缓存;
- 优先用组合而非重写:Golang 不支持多继承,组合天然契合适配器模式语义;
-
接口越小越好:比如只定义
Log()而非Log()/Debug()/Info()/Error(),降低适配成本。
适配器不是万能胶,而是精准对接的桥梁——写清楚“谁适配谁”“怎么转译”,Golang 的接口机制会让它既清晰又可靠。










