go 1.16起go get默认不修改go.mod,仅下载缓存;需加-u、指定版本或配合go mod tidy才能写入依赖,-d仅下载,vendor更新须显式加-mod=mod。

go get 不再自动写入 go.mod?这是默认行为
Go 1.16 起,go get 默认不再修改 go.mod,除非显式指定模块路径或使用 -d 以外的标志。你执行 go get github.com/sirupsen/logrus 后发现 go.mod 没变、代码里还报 import not found,不是命令错了,是 Go 故意“按兵不动”。
真正起作用的是:它只下载并缓存模块到本地 $GOPATH/pkg/mod,不触发依赖图更新,也不检查当前模块是否需要它。
- 要让依赖进
go.mod,必须加-u(升级)或直接在import语句后运行go mod tidy - 如果只是想下载不引入,用
go get -d github.com/sirupsen/logrus——-d表示“download only”,不会尝试编译或修改依赖声明 - 误用
go get而不跟go mod tidy,容易导致本地有包、CI 构建却失败(因为go.mod未记录)
go mod tidy 才是现代添加依赖的主力命令
与其纠结 go get 参数,不如把 go mod tidy 当作标准流程:先写 import,再运行它。它会自动解析源码里的 import 语句,下载缺失模块、移除未使用项、统一版本,并写入 go.mod 和 go.sum。
常见错误现象:go mod tidy 报 require github.com/xxx: version "v1.2.3" invalid: unknown revision v1.2.3,本质是 tag 不存在或私有仓库未配置认证。
立即学习“go语言免费学习笔记(深入)”;
- 确保
import路径拼写完全正确(大小写、下划线、组织名都不能错) - 私有 Git 仓库需提前配置
git config --global url."https://token@github.com/".insteadOf "https://github.com/"类似规则 - 若只想添加某版本(如
v1.8.0),可先go get github.com/xxx@v1.8.0再go mod tidy,避免自动升到最新预发布版
go get @version 的写法决定是否更新现有依赖
go get 后带版本号(如 @v1.10.0 或 @master)时,行为和不带版本完全不同:它会尝试更新该模块及其子依赖,并写入 go.mod —— 即使没 import,也会被记录为“require”。这常被用来强制降级或切分支。
但要注意:它不校验是否实际用到,容易把“幽灵依赖”留在 go.mod 里,后续 go mod tidy 也不会删掉它。
-
go get github.com/xxx@v1.5.0→ 强制设为 v1.5.0,即使已有 v1.9.0 -
go get github.com/xxx@7f8a2b1→ 基于 commit hash,适合临时调试,但不可移植(别人拉不到同 hash) -
go get github.com/xxx@latest→ 等价于不加版本,但明确表达意图;注意 latest 可能是 pre-release 版本
vendor 目录下依赖没更新?别忘了 -mod=mod
有些项目启用了 vendor,但运行 go get 后 vendor/ 里没变化——这是因为 Go 默认在 vendor 模式下跳过模块操作。必须显式告诉它:“请按模块方式处理”。
正确做法是加 -mod=mod 标志,例如:go get -mod=mod github.com/xxx,这样它才会更新 go.mod 并同步刷新 vendor/(配合 go mod vendor)。
- 单纯
go mod vendor不会下载新包,只把go.mod里已有的复制过去 - 如果
go list -m all | grep xxx显示版本不对,说明go.mod没生效,先检查是否漏了-mod=mod - CI 环境中建议统一用
GOFLAGS="-mod=mod",避免每个命令都补参数










