go list -m all 列出所有模块(含未引用的),不反映真实 import 关系;需结合 go mod graph 或 go list -f 分析依赖路径与包级引用,第三方工具如 gomodgraph 和 go-mod-outdated 更适合可视化与版本审计。

go list -m all 能看到所有模块依赖,但不反映实际引用关系
直接运行 go list -m all 会列出当前模块及所有间接引入的模块(含未被代码引用的),容易误判“真正用到的依赖”。它只读 go.mod,不分析源码 import 语句。
真正需要知道“哪个包引用了 github.com/sirupsen/logrus”,得结合源码扫描。常见误操作是仅靠该命令删掉“没出现在列表里”的模块——其实可能只是被 replace 或 indirect 标记掩盖了。
- 加
-u参数可显示可升级版本,适合审计过期依赖 - 加
-json输出结构化数据,方便脚本解析(字段如Path、Version、Indirect) -
Indirect: true表示该模块未被当前项目直接 import,而是由其他依赖引入
go mod graph 输出有向图,但默认太长需配合 grep 过滤
go mod graph 打印的是模块级依赖边(A → B 表示 A 依赖 B),每行一条,原始输出常达上千行。不加过滤基本无法人工阅读。
典型用法是定位某依赖的来源路径,例如查 golang.org/x/sys 被谁拉入:
立即学习“go语言免费学习笔记(深入)”;
go mod graph | grep 'golang.org/x/sys' | head -5
注意:输出中箭头方向是「依赖者 → 被依赖者」,和 import 关系相反(即你的 main.go import "net/http" → net/http 依赖 golang.org/x/net,图中表现为 net/http@v1.2.3 golang.org/x/net@v0.12.0)。
- 结果不含版本号时,说明该模块未被
go.mod显式约束,可能来自主模块的隐式升级 - 同一模块出现多行不同版本,代表存在版本冲突,go build 时会按最小版本选择(MVS)裁剪
- 管道接
sort | uniq -c | sort -nr可统计各依赖被引用次数
go list -f '{{.ImportPath}} {{.Deps}}' 遍历包级 import 依赖
若想确认某个具体 .go 文件是否真的 import 了 github.com/json-iterator/go,不能只看 go.mod,得查包级依赖树。用 go list 的模板功能可展开每个包的 Deps 字段:
go list -f '{{.ImportPath}} {{.Deps}}' ./... | grep jsoniter
该命令遍历当前目录下所有包(含子目录),输出形如 myproj/handler [fmt encoding/json github.com/json-iterator/go ...]。缺点是 Deps 是扁平字符串列表,不带层级,也不区分 direct/indirect。
- 替换为
-f '{{.ImportPath}}: {{join .Deps "\n "}}'可换行对齐,提升可读性 - 若报错
cannot load pattern ./...: invalid version,通常是某子目录含非法 go.mod,改用go list -f '...' $(go list -f '{{.Dir}}' ./... | grep -v vendor)绕过 - 该方式不识别条件编译(如
// +build ignore)或 _test.go 中的 import
第三方工具 gomodgraph 和 go-mod-outdated 更适合日常排查
原生命令适合一次性诊断,但长期维护建议用封装好的工具:gomodgraph 可生成 PNG/SVG 依赖图(需 Graphviz),go-mod-outdated 则专注版本陈旧度检测。
安装后直接运行:
go install github.com/loov/gomodgraph@latest<br>gomodgraph -s -l > deps.dot && dot -Tpng deps.dot -o deps.png
生成的图中,节点大小反映被引用频次,颜色区分主模块/间接依赖。而 go-mod-outdated -v 会标出哪些模块有新版本、是否破坏兼容性(基于 semver patch/minor/major 判断)。
-
gomodgraph -s开启简化模式,折叠重复路径,否则 vendor 内部依赖会撑爆图像 - 两个工具都不分析 replace 后的实际路径,若用了
replace github.com/foo => ../foo,图中仍显示原始域名 - CI 中建议用
go-mod-outdated -update=patch检查是否存在可安全升级的补丁版本
依赖分析真正的难点不在命令怎么敲,而在理解「模块版本」和「包导入路径」的分离设计:同一个 github.com/gorilla/mux 模块,可能被三个不同版本的父模块各自 import,最终生效的只有一个。这时候看 go mod graph 的边比看 go list -m 的列表更能暴露冲突源头。










