真正的防腐层必须切断外部API对核心域的渗透:自定义struct解析响应、统一转换外部错误、adapter仅持最小依赖、interface覆盖全部调用路径,且不承担重试熔断等横切关注点。

真正的防腐层不是加个adapter包就完事,而是必须切断外部 API 的数据结构、错误类型和行为语义对核心域的渗透。否则一次 Stripe SDK 升级或支付网关返回 429 Too Many Requests,就会让订单创建流程直接 panic 或误判为业务失败。
用自定义 struct 解析响应,别复用第三方 model
外部 HTTP 响应或 gRPC message 必须在进入 domain 层前完成彻底解耦:不 import 第三方 SDK 的 struct,不嵌套其字段,不透传其 tag(比如 json:"object")。
- ✅ 正确:定义
type PaymentResp struct { ID string `json:"id"` Status string `json:"status"` },用json.Unmarshal解析原始[]byte - ❌ 错误:
type PaymentResp stripe.PaymentIntent或struct { Inner *stripe.PaymentIntent } - ⚠️ 风险:第三方 struct 字段改名、新增必填字段、tag 变更,会导致
json.Unmarshal静默失败或 panic,且错误堆栈指向你自己的 handler
所有外部错误必须转成 domain error,禁止透传 context.DeadlineExceeded 等
HTTP client 超时、gRPC Canceled、数据库连接中断——这些都不是业务错误,不能被 usecase 当作“用户余额不足”处理。
- ✅ 正确:在 adapter 方法里用
errors.As(err, &url.Error{})或status.Code(err) == codes.DeadlineExceeded捕获后,统一转为ErrPaymentTimeout或ErrThirdPartyUnavailable - ❌ 错误:直接
return err,让上层用errors.Is(err, context.DeadlineExceeded)做分支判断 - ⚠️ 风险:业务逻辑被迫感知网络层细节;测试时 mock 失败路径需构造底层 error 类型,耦合度爆炸
adapter struct 必须持有最小依赖,别塞进 *stripe.Client 这种大对象
*stripe.Client 内部封装了 HTTP transport、重试逻辑、签名、日志,它不是 adapter 的依赖,而是你要隔离的对象。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- ✅ 正确:adapter struct 只持
httpClient *http.Client和必要配置(如apiBaseURL),所有请求走自己封装的doRequest(ctx, method, url, body) - ❌ 错误:
type StripeAdapter struct { client *stripe.Client },然后在方法里调a.client.Charges.New(...) - ⚠️ 风险:无法在测试中替换 transport;无法统一注入 trace ID 或打点日志;重试策略与熔断混在 SDK 里,不可控也不可观测
interface 定义必须覆盖真实调用路径的所有分支
别只定义 Charge(ctx, req) 就完事。真实支付流程还有取消、查询、退款、Webhook 验证——这些行为都得出现在 interface 里,否则 usecase 只能绕过防腐层直连 SDK。
- ✅ 正确:
type PaymentService interface { Charge(...) error; Cancel(...) error; Get(...) (*Payment, error); VerifyWebhook(...) error } - ❌ 错误:interface 只有
Charge,结果Cancel逻辑散落在 handler 里,直接 newstripe.Client - ⚠️ 风险:领域逻辑被撕裂;测试时部分路径无法 mock;后续接入支付宝时,
Cancel行为缺失导致新 adapter 不完整
最容易被忽略的一点是:防腐层不该管重试、熔断、降级。这些属于 cross-cutting concern,该由 go-zero 的 breaker 或独立 middleware 承担。把它们塞进 adapter,等于把胶水层变成混凝土块——既难测,也难换。

















