go get -u 只升直接依赖,因默认仅更新 import 列表中的模块,跳过 // indirect 依赖;全量升级需用 go get -u ./ 或 go get -u all。

go get -u 为什么只升直接依赖,不碰间接依赖?
因为 go get -u 默认行为就是“只更新 import 列表里出现的模块”,不会递归处理 // indirect 标注的依赖。这容易让人误以为它在“全量升级”,结果上线后发现 golang.org/x/net 还卡在 v0.14.0 —— 它根本没被 go get -u 触及。
- 真正生效的全量升级命令是:
go get -u ./(当前目录所有包)或go get -u all(Go 1.16+,且 module-aware 模式下) -
go get -u会跳过replace和exclude声明的模块,连检查都不做 - 如果
GOFLAGS="-mod=readonly"已启用(Go 1.17+ 默认),go get会直接报错,不是静默失败
go mod tidy 怎么偷偷改掉你的版本?
go mod tidy 不是“整理依赖”,而是运行最小版本选择(MVS)算法重新计算整个依赖树。它会拉取满足所有约束的“最低可行版本”,而不是你写死的那个。
- 比如你手动写
github.com/sirupsen/logrus v1.8.1,但另一个依赖要求v1.9.0,go mod tidy就会把它升到v1.9.0 - CI 流水线每次 clean 构建 +
go mod tidy,若上游发布了新 patch 版本,就会自动固化进去,导致不同时间构建结果不一致 - 想避免?改用
go mod download+go build -mod=readonly,跳过tidy和get环节
为什么 go get github.com/pkg@v1.5.3 后版本没变?
这不是命令失效,是 MVS 在拒绝你——它优先满足全局约束,而不是你敲的那条命令。
- 已有其他依赖 require
github.com/pkg/v2?那@v1.5.3直接被忽略,v1 和 v2 是不同模块路径 - 想确认 tag 是否真实存在:
curl -I https://proxy.golang.org/github.com/pkg/@v/v1.5.3.info - 想强制写入且不触发升级:
go mod edit -require=github.com/pkg@v1.5.3,再跑go mod tidy - 想锁定 commit 而非 tag:
go get github.com/pkg@e8f4a5c
replace 用错会彻底失效
replace 是路径重写,不是版本覆盖。它只影响 import 解析路径,不改变依赖树结构。
- 代码仍 import
github.com/old/pkg,但replace github.com/old/pkg => github.com/old/pkg v2.0.0—— 完全无效,因为 import 路径没变,v2 的路径应是github.com/old/pkg/v2 - 验证是否生效:
go list -m all | grep old/pkg,输出里必须有=>才表示重定向成功 - CI 构建中残留
replace会导致 panic:它绕过go.sum校验,不同 GOPROXY 下行为可能不一致
真正难缠的不是某条命令,而是 MVS 算法和 SemVer 规则共同作用下的隐式决策——它不报错,只默默选一个“看起来最合理”的版本,而这个“合理”未必是你想要的。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











