go mod tidy 默认升级到满足 require 约束的最新小版本(如 v1.9.0 → v1.9.3),不降级也不保证最小版本;require 是下界声明,隐式升级由依赖图决定,需用 go list -m -versions 和手动编辑 go.mod 控制版本。
执行 go mod tidy 时,Go 不是“锁死”当前已用版本,而是根据 go.mod 中声明的 require 约束(如 github.com/sirupsen/logrus v1.9.0 或 v1.9.0),拉取满足该约束的**最新可用小版本**(比如从 v1.9.0 升到 v1.9.3)。它不会主动降级,但也不会保证你“只用最小合法版本”——除非你手动指定。
Go 没有内置 “–min-version” 参数,但可通过组合命令逼近最小可用版本:
go get -u=patch github.com/sirupsen/logrus:仅更新补丁版本(v1.9.0 → v1.9.3),不跨次要版本(v1.9.x → v1.10.0)v1.8.1),需先查清最小兼容版本:运行 go list -m -versions github.com/sirupsen/logrus,再手动编辑 go.mod 中对应行,改为 github.com/sirupsen/logrus v1.8.1
go mod tidy,否则可能
因依赖冲突导致构建失败即使你把 A 的版本写死为 v1.2.0,若另一个依赖 B 要求 A v1.5.0+,Go 会自动将 A 升级到 v1.5.0(或更高)以满足约束。这是 Go module 的语义化版本解析规则决定的,无法绕过。
验证方式:
go mod graph | grep 'github.com/sirupsen/logrus'
查看哪些模块在拉取它,以及它们各自声明的最小版本要求。
require 行不是“锁定”,而是“下界声明”。以下写法含义不同:
github.com/sirupsen/logrus v1.9.0:允许 ≥ v1.9.0 的任何兼容版本(v1.9.x, v1.10.x 都不行,v2.0.0 更不行)github.com/sirupsen/logrus v1.9.0 // indirect:表示该版本由其他模块引入,非你直接依赖;go mod tidy 可能删掉它,也可能升级它// indirect 但版本号带 +incompatible:说明该模块未遵循 Go module 版本规范(如没打 v1.2.3 tag),Go 会按伪版本处理,行为更难预测真正“最小可用”的实践,往往是在 CI 中加一步检查:go list -m all | awk '{print $1,$2}' | sort 对比 baseline,发现意外升级就阻断发布。