go mod 是 go 1.11+ 唯一官方依赖管理机制,必须用 url 格式显式初始化(如 go mod init github.com/user/proj),禁止裸名;require 不支持 ^/~ 版本符号;go mod tidy 按 import 自动同步依赖,go.sum 保障校验完整性。

go mod 是 Go 1.11+ 唯一官方支持的依赖管理机制,不用它就等于在用过时的 GOPATH 模式,构建不可重现、协作易出错、版本无法锁定。
go mod init 必须指定明确的模块路径
执行 go mod init 时不填参数或填本地路径(如 go mod init myproject),会导致 go.mod 中的 module 行变成无域名的裸名,后续导入时其他项目无法正确解析该模块——Go 工具链会把它当成“伪模块”,go get 失败、CI 构建报 unknown revision。
- 正确做法:用可解析的 URL 形式,如
go mod init github.com/yourname/yourproject - 模块路径就是将来别人
import你包时写的路径,必须稳定、唯一、能被 Git 或其他 VCS 映射到实际仓库 - 如果项目暂未托管,也应模拟真实路径(如
example.com/yourproject),后期迁入 GitHub 后只需改远程地址,无需改go.mod或源码 import 语句
require 版本号必须精确,别信 ^ 或 ~
Go Modules 不支持 npm 风格的 ^1.2.3 或 ~1.2.0 写法。你在 go.mod 里手动写这种符号,go mod tidy 会直接删掉或报错;而 go get 默认拉取的是满足约束的「最小兼容版本」(MVS 算法结果),不是最新版。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 显式指定版本:用
go get github.com/gin-gonic/gin@v1.9.1,go.mod会记为github.com/gin-gonic/gin v1.9.1 - 避免
@latest:它可能指向非语义化 tag(如v0.0.0-20240512102345-abc123),CI 上行为不稳定 - 间接依赖(
// indirect)不用管,go mod tidy会自动标记;但若某依赖只用于测试,却出现在require主列表里,说明代码中存在未清理的 import
go mod tidy 不是“一键修复”,它会删依赖也会加依赖
go mod tidy 的本质是:扫描所有 .go 文件中的 import,对比 go.mod,补全缺失的 require,并移除未被任何 import 引用的条目。它不区分“开发依赖”和“生产依赖”——Go 没有这个概念。
- 运行前确保所有
import都已写完,否则它会把刚删掉的依赖又加回来 - 如果项目含
// +build ignore或build tags的文件(如main_linux.go),go mod tidy默认不扫描它们,可能导致依赖遗漏;加-compat=1.20或显式指定 build tag 才能覆盖 - 执行后务必检查
go.sum是否新增了校验行——若没变,说明依赖没真正下载,可能是网络问题或GOPROXY配置失效
vendor 目录不是“备用方案”,而是构建确定性的最后防线
go mod vendor 把所有依赖源码复制进项目根目录下的 vendor/,之后 go build -mod=vendor 就完全不碰网络和 $GOPATH/pkg/mod 缓存。但它不是默认开启的,也不是越早用越好。
- 仅在需要离线构建、审计依赖源码、或 CI 环境无法信任代理时启用
- 启用后必须配合
go build -mod=vendor,否则 Go 仍会走模块模式,vendor/被忽略 -
vendor/不解决版本冲突:如果两个依赖要求同一包的不同 major 版本(如v1和v2),go mod vendor会失败,得靠replace或升级上游 - 别把
vendor/提交到 Git?错。只要用了它,就必须提交——否则“可重现构建”就是空话
最常被忽略的一点:go.sum 不是校验缓存,而是构建锁。它记录的是每个模块内容的哈希值,一旦有人篡改依赖源码(哪怕是私有库 commit),go build 就会报 checksum mismatch 并中断——这不是 bug,是设计使然。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










