依赖必须显式传入结构体字段,禁用全局变量和init();wire仅生成编译期静态初始化代码,不支持运行时逻辑;跨服务调用须通过http/grpc客户端隔离,禁止直接import其他服务结构体;go.mod和go.sum是强制依赖契约,必须严格维护。

依赖必须显式传入结构体字段,别碰全局变量和init()
Go 没有运行时 DI 容器,硬塞 init() 或包级变量(如 var db *sql.DB)会让依赖关系不可见、无法替换、测试时难 mock。一旦某个服务启动失败,整个进程 panic,但错误堆栈常指向无关代码,排查成本极高。
正确做法是把所有外部依赖作为结构体字段,在构造函数中由调用方传入:
-
UserService依赖*sql.DB和*zap.Logger,就定义type UserService struct { db *sql.DB; logger *zap.Logger } - 构造函数只做赋值,不 new、不 connect、不读配置:
func NewUserService(db *sql.DB, logger *zap.Logger) *UserService - main 包负责组装:先建
db,再建logger,最后传给NewUserService
这种写法让依赖一目了然,单元测试时可直接传入 mock 实例,无需启动真实数据库。
wire.Build 生成初始化代码,但别指望它处理运行时逻辑
wire 是目前最稳妥的编译期 DI 工具,它不反射、不 runtime,生成的代码就是普通 Go 函数,可 debug、可 profile。但它只解决“谁先建、谁后建、谁复用”的静态图问题,不支持条件分支或环境切换。
比如你不能在 InitializeService() 里写 “如果环境是 staging,用 mock cache;否则用 redis”。这类逻辑必须提前提炼成不同 provider 函数,再通过构建 tag 或不同 wire 文件区分:
- 定义
func NewCacheStaging() *cache.MockCache和func NewCacheProd() *redis.Client - 在
//+build prod文件中调用wire.Build(NewCacheProd, ...) - 在
//+build staging文件中调用wire.Build(NewCacheStaging, ...)
忘记这点,强行塞 if-else 到 provider 函数里,wire generate 会报错或生成不可靠代码。
跨服务调用必须走客户端,禁止 import 其他服务的结构体
微服务边界不是靠文件夹或命名空间划的,而是靠进程隔离。常见反模式是 A 服务直接 import "github.com/org/user-svc/internal/model",然后把 User 结构体当参数传给本地方法——这等于把 B 服务的内部契约硬编码进 A,B 一改结构,A 就挂。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
正确姿势只有两种:
- HTTP 场景:A 用
http.Client调 B 的 REST 接口,返回 JSON 后用本地struct解析(不复用 B 的 struct) - gRPC 场景:A 引入 B 的
.proto文件生成 client stub,调用时用生成的 request/response 类型
哪怕两个服务共用一个 Git 仓库,也要严格隔离 domain model。否则服务拆分就只剩目录结构,没有真正解耦。
go.mod 和 go.sum 不只是构建工具,它们是依赖契约的法律文件
go.mod 的 module 路径不是项目名,而是未来别人 import 你的路径,必须写成完整 URL(如 github.com/yourorg/auth)。写成 auth 或 myauth,CI 构建时会因 GOPROXY 无法解析而失败。
go.sum 更关键:它不是缓存,是每个依赖包的 SHA256 校验和快照。删掉或不提交,团队成员拉代码后可能装上被篡改或版本错乱的包——这不是“可能”,是必然发生。
实际踩坑点集中在两处:
- CI 流水线没跑
go mod verify,上线前才发现某间接依赖哈希不匹配 - 私有模块未配
GOPRIVATE=git.company.com/*,导致go.sum校验时去连官方 sumdb 失败
依赖管理最终不是技术选型问题,而是协作契约问题。wire 可以换,但 go.sum 一旦松动,信任就崩了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










