go list -m -f '{{.Path}} {{.Version}}' -u 精准显示 go.mod 中显式 require 的模块及其实际解析版本(含伪版本或 (devel)),并附带可升级提示,不包含间接依赖;而 go list -m all 列出全部依赖(含间接),易淹没主动声明项。

直接运行 go list -m -f '{{.Path}} {{.Version}}' -u,它只显示你 go.mod 里显式 require 的模块及其解析后的版本,不含间接依赖。
为什么不用 go list -m all?
因为 go list -m all 会把整个依赖树(包括所有间接依赖)都列出来,少则几十、多则上百行,真正“你主动选的”反而被淹没。而 -u 参数本身不触发升级,只是让输出带上可升级提示(如 [v1.9.0]),顺便过滤掉间接依赖——这是 Go 官方文档明确说明的行为。
-
go list -m all:适合查“最终构建用了哪些模块”,但不是“我写了哪些 require” -
go list -m -f '{{.Path}} {{.Version}}' -u:精准对应go.mod中的require块,.Version是实际解析出的语义化版本或伪版本(如v0.0.0-20230101000000-abcdef123456) - 如果某依赖用了
replace,.Version会显示(devel),这不是错误,而是 Go 明确告诉你:“这里没走远程版本,是本地路径”
go.mod 里写的是 v1.2.3,但 go list 显示 v1.2.4 ——怎么回事?
常见于以下几种情况:
- 你执行过
go get github.com/foo/bar@v1.2.4,它自动更新了go.mod,但你没注意 -
go.mod中该依赖被exclude或replace影响,go list反映的是实际解析结果,不是文本原样 - 项目启用了
GOINSECURE或自定义GOPROXY,导致模块解析时 fallback 到不同源,版本号可能漂移
验证方式:对比 cat go.mod | grep 'github.com/foo/bar' 和 go list -m -f '{{.Path}} {{.Version}}' -u | grep 'github.com/foo/bar',差值就是生效逻辑。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
想确认某个包是否真被当前项目“直接 require”,而不是被其他依赖带进来的
用 go mod graph 配合 grep 更可靠:
- 先获取主模块名:
go list -m - 再查它到目标包的边:
go mod graph | grep "^$(go list -m) " | grep 'github.com/foo/bar' - 如果输出为空,说明不是直接依赖;有输出(如
my/project github.com/foo/bar@v1.2.3),才是你require的
注意:go mod graph 不受 replace 影响,它显示的是原始依赖声明,所以看到的仍是 github.com/foo/bar@v1.2.3,哪怕你本地 replace 了它——这点和 go list 行为不同,要区分清楚。
最容易被忽略的是:Go 没有“安装即可见”的全局包列表,go list -m -f 输出的每个 .Version 都是在当前模块上下文里解析出来的结果,换个项目、换个 GO111MODULE 状态,甚至换个 GOPROXY 配置,都可能不同。

















