go get -u=patch 是唯一推荐的“无害升级”方式,它仅将 v1.9.1 → v1.9.2 类补丁版本升级,绝不触碰次版本或主版本,天然规避 api 不兼容风险,执行后必须跟 go mod tidy 并验证构建与测试。

go get -u=patch 只升补丁版,最安全的日常更新
想改自己本地依赖又不破坏团队协作?go get -u=patch 是唯一推荐的“无害升级”方式。它只把 v1.9.1 → v1.9.2 这类补丁级版本拉上来,绝不会动 v1.9.x → v1.10.0(次版本)或 v1.x → v2.x(主版本),天然避开 API 不兼容风险。
常见误操作是直接 go get -u,结果 golang.org/x/net 从 v0.21.0 跳到 v0.22.0,而某中间件恰好用了被删掉的 http2.ConfigureServer,本地编译就挂了——这种问题 -u=patch 根本不会触发。
- 只作用于当前模块下所有直接依赖(
import列表里的)及其子树中满足补丁兼容的间接依赖 - 跳过
replace和exclude声明的模块,不碰私有/调试用依赖 - 执行后必须跟
go mod tidy,否则新增的补丁版可能没进go.sum,CI 上会校验失败
go list -m -u=patch 查看可升项,避免盲更
别猜哪个包有新补丁——先跑 go list -m -u=patch。它不改任何文件,只输出当前 go.mod 里哪些模块有可用的补丁更新。加上 -f '{{.Path}}: {{.Version}} → {{.Latest}}' 能一眼看清变化范围。
注意:如果某个依赖写的是 github.com/sirupsen/logrus v1.8.0+incompatible,这个命令可能漏报,因为 +incompatible 表示非语义化版本,proxy 不保证提供完整历史记录。
- 加
all(即go list -m -u=patch all)会包含间接依赖,但耗时明显增加,日常开发没必要 - 遇到
unrecognized import path报错?不是命令错了,是GOPRIVATE没配,私有模块被代理拦截了 - 输出里看到
v1.9.1 → v1.9.2就放心升;要是出现v1.9.1 → v2.0.0,说明你写的约束太松,得回去收紧require行
go mod tidy -compat=1.21 强制适配新 Go 版本,不是升级依赖本身
当你升级 Go 到 1.21 后发现某些包编译失败,别急着 go get -u。先试 go mod tidy -compat=1.21。它不改依赖版本号,而是让工具链按 Go 1.21 的语义重新解析 go.mod,自动调整那些声明了 +incompatible 或未标 // indirect 的模块引用方式,以满足新编译器的约束。
比如 golang.org/x/tools 在 Go 1.20 下能用 v0.15.0,到了 1.21 就要求至少 v0.16.0 才能通过类型检查——tidy -compat 会帮你补上这行 require,而不是硬升到 v0.17.0 引发其他问题。
- 这个参数只影响
go.mod解析逻辑,不会下载新代码,也不会改go.sum里的哈希 - 必须配合
GO111MODULE=on使用,否则在 GOPATH mode 下无效 - 执行后若
go build仍失败,说明是依赖自身不兼容,这时才该查它的 release note 再决定是否手动go get @vX.Y.Z
更新后不验证 import 和 build,等于白干
go get 和 go mod tidy 都不会检查你的代码是否还调得通。比如 logrus 升到 v1.9.2 后移除了 Logger.Out 字段,而你代码里还直接赋值,go get 完全不管,直到 go build 才报错。
更隐蔽的是 import 路径错位:你写了 import "utils",但 go.mod 里 module 是 example.com/myapp,正确路径应为 example.com/myapp/utils。这种错误只有 go build 或 go test 时才会暴露为 no required module provides package utils。
- 每次
go get或go mod tidy后,必须立刻跑go build ./...和go test ./... - CI 中建议加
go mod verify,它会比对go.sum里每个模块的哈希和实际下载内容,防止代理源篡改或缓存污染 - 本地调试时若怀疑缓存异常,用
go clean -modcache清掉重来,但别在 CI 里用——它会让构建变慢且不可复现











