go list -m -u all 只列出可升级的模块,不修改 go.mod 也不下载新版本;带方括号(如 [v0.3.0])表示真有新版,无括号则已最新或受版本约束限制。

go list -m -u all 能查到什么,但不能做什么
它只输出可升级的模块列表,不修改 go.mod,也不下载新版本。常见错误是把它当“自动更新命令”用,结果跑完发现依赖一点没变。
- 输出里带方括号的(如
golang.org/x/net v0.0.0-20210220032951-0396af6a65e0 [v0.3.0])才是真有新版;没括号的要么最新,要么受限于语义版本约束 -
go list -m -u all会扫描所有间接依赖,但私有模块若没配GOPRIVATE,直接报unrecognized import path,不是命令错了,是网络策略卡住 - 如果某个模块 require 写的是
+incompatible,比如github.com/sirupsen/logrus v1.8.0+incompatible,go list的判断可能不准——proxy 不保证提供非语义化版本的完整历史
go get -u ./ 和 go get -u all 的实际行为差异
go get -u 默认只升直接依赖,这是最容易被忽略的坑。你以为全树更新了,其实 golang.org/x/sys 这类间接依赖还卡在旧版。
-
go get -u ./:作用域是当前模块下的所有包,会递归更新直接 + 间接依赖,但跳过replace和exclude条目 -
go get -u all:Go 1.16+ 支持,效果类似./,但更彻底——连 vendor 外的隐式依赖也扫,不过 CI 中慎用,耗时明显增加 -
go get -u=patch ./:只升补丁级(如 v1.2.3 → v1.2.4),避免 minor 版本带来的 API 变更风险
Dependabot 和 Renovate 的关键配置点
它们不是“开箱即用”,默认配置常漏掉 Go 模块特有的约束,比如 // indirect 标注或 replace 规则。
- Dependabot 需在
.github/dependabot.yml中显式启用gomod更新器,并设versioning-strategy: auto,否则可能跳过indirect依赖 - Renovate 的
renovate.json要加"packageRules": [{"datasources": ["github-tags"], "semanticVersioning": true}],否则对+incompatible版本处理容易出错 - 两者都默认忽略
replace条目——如果你用replace example.com/lib => ./local/lib做本地开发,自动化工具根本不会碰它,也不会提醒你该同步 upstream
CI 中触发更新前必须确认的三件事
自动更新失败往往不是工具问题,而是环境锁死或权限缺失。CI 脚本里漏掉任一检查,就会卡在 go get 报错。
- 确认
GOFLAGS没设-mod=readonly(Go 1.17+ 默认启用),否则go get直接拒绝写go.mod - 确保
GOPROXY可达,尤其私有模块——若用了GOPRIVATE=git.internal.company.com,CI 环境变量必须同步设置 -
go mod tidy必须跟在go get后执行,否则新增依赖可能没进go.sum,导致后续构建校验失败
go test ./... 过不了,go build 报 undefined: some.NewFunc,这些都得靠你自己的测试覆盖和人工 review —— 工具只负责把版本号换掉,不负责 API 兼容性。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











