最稳的更新方式是go get github.com/xxx/yyy@v1.2.3,它只更新目标包、不递归升级间接依赖;必须显式带@指定版本,否则可能跨主版本导致编译失败;执行后自动更新go.mod和go.sum,但需再运行go mod tidy同步未引用的新增依赖。

更新依赖不是“装新包”,而是改 go.mod 并同步缓存——不运行 go get 或 go mod tidy,只改文件没用;不提交 go.mod 和 go.sum,协作者根本复现不了。
go get github.com/xxx/yyy@v1.2.3 是最稳的更新方式
这是日常维护中最可控、副作用最小的操作。它只动目标包,不碰其他依赖,也不会递归升级间接依赖。
- 必须带
@显式指定版本,否则默认拉latesttag,可能跳 major 版本(比如 v1 → v2),而 Go 要求 v2+ 必须改 import 路径,否则编译失败 - 版本号可以是
v1.2.3、@master(不推荐)、@3f5e566(commit hash),后两者会在go.mod里生成伪版本号,如v1.2.3-0.20260520101522-3f5e566 - 执行后自动更新
go.mod和go.sum,但不会下载未被代码引用的包——如果只是加了依赖还没 import,得再跑一次go mod tidy
go get -u 不等于“一键升级”,它默认只升 direct 依赖
go get -u github.com/xxx/yyy 和 go get -u ./ 行为差异很大,很多人误以为后者会“全量升级”,其实它只升级当前模块下所有 直接依赖 及其子树中满足语义化兼容规则的版本(即保持主版本号不变)。
-
go get -u不加路径时,只作用于当前目录下的 main 包或库包,且仅更新其直接依赖 -
go get -u ./...才会遍历所有子目录包,但仍不升级// indirect标记的间接依赖,除非它们被某个 direct 依赖的新版本重新引入 - 想强制升 patch 级别(如 v1.9.1 → v1.9.2),用
go get -u=patch ./,这在生产环境更安全
go mod tidy 不是“整理命令”,它是依赖图的校验器
它不凭空猜你要什么,而是扫描所有 .go 文件里的 import,然后比对 go.mod 中是否有对应 require。缺了就加,多了就删,go.sum 也一并刷新。
立即学习“go语言免费学习笔记(深入)”;
- 常见报错
no required module provides package xxx,基本就是 import 路径和go.mod里声明的 module 名不匹配(比如写了import "utils",但 module 是example.com/myapp,正确应为example.com/myapp/utils) - 如果本地有未提交的
go.mod修改(比如手动删了一行),go mod tidy会把它还原回来——它只信代码里的 import,不信你手写的 require - CI 中必须跑
go mod tidy -v,加-v能看到它实际增删了哪些模块,方便快速定位意外变更
更新后不验证,等于没更新
Go 不会在 go get 后自动检查你的代码是否还能编译、是否调用了已移除的函数。很多 breakage 发生在升级后第一轮测试才暴露。
- 至少跑
go build ./...和go test ./...,不要只测 main 包 - 如果项目用了
replace指向本地路径,升级前先确认那个本地包本身也兼容新版本(比如你replace github.com/foo/bar => ./bar,那./bar的go.mod也得同步更新) -
go.sum文件必须提交——它不是缓存,是校验锁。漏提会导致别人go build时因 checksum 不匹配而失败,错误信息是checksum mismatch


















