适配器通过持有第三方库对象指针并显式实现接口方法来封装调用,需透传context、映射错误、转换参数,禁止嵌入第三方结构体或添加业务逻辑。

适配器里怎么调用第三方库方法
适配器本身不“调用”第三方库,而是把调用逻辑封装进自己实现的方法里——关键在于持有原对象引用,并透传参数。比如你封装 *s3.Client,就得在适配器结构体里存一个 client *s3.Client 字段,而不是每次新建。
- 必须用指针持有被适配者(
*ThirdPartyClient),否则无法调用其方法 - 不能在适配器方法里 new 一个新的 client 实例,会丢失连接池、中间件、配置等上下文
- 所有参数要原样或按需转换后传给底层方法,比如把
io.Reader转成io.ReadSeeker以满足 S3 SDK 要求 - 错误不能直接返回,得做映射:把
*smithy.OperationError包装成你自己的StorageError
为什么不能直接嵌入第三方结构体
Go 没有继承,嵌入结构体只有在它本身实现了目标接口时才自动满足契约;而第三方库的 struct 几乎从不实现你的接口。例如 *s3.Client 不实现你定义的 ObjectStorer,强行嵌入:type S3Adapter struct { *s3.Client },编译会报 cannot use s3Client as type ObjectStorer。
- 嵌入只对“已实现接口的类型”有效,第三方 struct 是黑盒,方法名/签名都不受你控制
- 即使嵌入成功,也无法控制方法行为(比如加日志、重试、context 透传)
- 正确做法是显式声明字段 + 显式实现每个方法,哪怕只是转发
适配器里 context 怎么传才不丢 cancel 信号
必须把调用方传进来的 ctx context.Context 原样传给第三方库方法,不能在适配器里用 context.WithTimeout(context.Background(), ...) 替换。
- 第三方 client(如
*http.Client、*s3.Client)依赖ctx做请求取消和超时,替换就等于切断上游控制链 - 如果需要加超时,应该由调用方决定,比如
ctx, _ := context.WithTimeout(parentCtx, 5*time.Second) - 适配器里唯一合法的 context 操作是
ctx = ctx // just pass through,别碰它
反射调用第三方方法时参数怎么塞进去
用 reflect.ValueOf() 把原始值转成 reflect.Value,再构造成切片传给 Call();但接收者和参数都必须是指针,且类型要和方法签名完全一致。
- 接收者必须是可寻址的:传
&Client{},不能传Client{},否则MethodByName()返回无效值 - 参数也要传指针:方法签名为
func(*Client, *Request),就得用[]reflect.Value{reflect.ValueOf(&req)} - 结构体字段必须导出(首字母大写),否则反射不可见
- 别在生产代码里滥用反射——它绕过编译检查,出错只在运行时报 panic
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











