go.mod 是微服务独立生存的基石,划定边界、锁定版本、隔离依赖,确保单个服务可构建、可复现、不被上游破坏;每个微服务应有独立 go.mod 文件,禁止共用模块路径或塞入 mega-module。

Go模块(go mod)不是微服务的“胶水”,而是每个服务独立生存的基石——它划定边界、锁定版本、隔离依赖,不解决服务间通信,只确保单个服务可构建、可复现、不被上游意外破坏。
go.mod 是服务级而非项目级的单元
一个微服务就是一个独立模块,对应一个 go.mod 文件。它不该和其它服务共用同一个模块路径,也不该把所有服务塞进一个 mega-module 里。
- 错误做法:根目录
go mod init company/project,所有服务子目录共享同一模块路径 - 正确做法:每个服务目录下单独执行
go mod init svc/user、go mod init svc/order - 后果:共用模块会导致
go.sum冲突、升级牵一发而动全身、无法按需发布单个服务
require 中的依赖必须严格区分“本服所用”和“跨服调用”
go.mod 的 require 只管当前服务直接 import 的包,不包含它调用的其他微服务代码。后者属于运行时契约,由 proto + gRPC client 或 HTTP client 实现,不进依赖列表。
- 应出现在
require中的:如google.golang.org/grpc v1.62.0、github.com/go-sql-driver/mysql v1.8.0 - 不应出现的:其它服务的 Go 代码路径(如
company/svc/payment),哪怕本地有源码也不该replace进来 - 替代方案:用
protoc生成 client stub,或通过go get引入已发布的 SDK 模块(如github.com/company/sdk/v2)
私有模块与 GOPRIVATE 配置容易漏掉
微服务常依赖公司内部的通用库(如 git.internal.company.com/go/logutils),若没配 GOPRIVATE,go mod download 会失败或走代理返回 404。
立即学习“go语言免费学习笔记(深入)”;
- 必须在 CI/CD 环境和本地开发机都设置:
go env -w GOPRIVATE=git.internal.company.com/* - 不能只靠
replace临时绕过:它只影响当前模块构建,不解决依赖传递问题 - 验证方式:
go list -m all | grep internal应正常显示版本,而非(devel)或报错
go mod vendor 不是微服务部署的必需项
容器镜像中更推荐多阶段构建 + go build -mod=readonly,而非 go mod vendor。后者易引入冗余文件、掩盖未声明依赖、且与 go.sum 校验逻辑脱节。
- vendor 目录不会自动更新:
go mod tidy后需手动go mod vendor,否则构建可能失败 - Dockerfile 中若用了
COPY . .却忽略/vendor,会导致构建失败;若复制了却没go mod vendor,则内容过期 - 真正需要的是确定性:只要
go.mod和go.sum在,go build就能复现,vendor 只是可选缓存
模块边界一旦划错,后面的服务拆分、CI 分流、灰度发布都会卡在依赖上。最常被忽略的,是把 proto 生成代码或 client SDK 当作“内部实现”硬塞进本服模块——它们本质是 API 契约,应作为独立模块发布和消费。


















