go mod graph 输出文本格式的模块依赖有向边,需配合 grep 等命令过滤分析,不处理 replace/exclude,vendor 项目需先执行 go mod vendor。

用 go mod graph 快速导出依赖边
这是 Go 官方自带、零安装的轻量级入口。它不画树、不渲染,只输出文本形式的有向边:github.com/user/app golang.org/x/text@v0.14.0,每行代表一个模块对另一个模块的直接引用关系。
常见错误是直接跑 go mod graph 后面对上千行无从下手。实际应配合 grep 过滤:
- 查主模块直接依赖:
go mod graph | grep "^$(go list -m) " | cut -d' ' -f2 - 找某个高危包(如
gopkg.in/yaml.v2)被谁引入:go mod graph | grep 'gopkg.in/yaml.v2' - 筛出重复版本:
go mod graph | awk '{print $2}' | sort | uniq -c | grep -v ' 1 '
注意:go mod graph 不处理 replace 和 exclude,输出仍是原始路径;若项目用了 vendor,需先 go mod vendor 再执行,否则结果失真。
用 gomodtree 看缩进式依赖树
比 go mod graph 多一层结构感,输出类似 tree 命令的缩进层级,能一眼看出嵌套深度和重复子树。安装只需:go install github.com/icholy/gomodtree@latest(别装已归档的 loic-lopez 版本)。
运行 gomodtree 默认从当前 module 展开,支持加参数指定模块,例如:gomodtree github.com/your/app。它会标出 (indirect) 和 (replace),但依赖本地 go.sum 和模块缓存——CI 环境刚拉代码没执行过 go mod download,可能漏掉部分间接依赖。
真正容易被忽略的是:它不展示版本冲突。比如 golang.org/x/net 被两个上游分别拉了 v0.7.0 和 v0.14.0,树里只会显示其中一个(MVS 选中的版本),另一条路径被隐去。
用 go list -m all + grep 定位可疑模块
go list -m all 是最轻量、最确定的模块清单命令,输出当前项目所有模块及其版本,格式为 module/path v1.2.3。它尊重 replace 和 exclude,且不依赖外部工具。
关键在于怎么筛。常见场景:
- 找半年未更新的间接依赖:
go list -m -f '{{if .Indirect}}{{.Path}} {{.Version}}{{end}}' all | grep -E '\.[0-9]+$' | awk '{print $1}' | xargs -I{} sh -c 'curl -s "https://pkg.go.dev/{}?tab=versions" | grep -oE "v[0-9]+\.[0-9]+\.[0-9]+" | head -n1'(需配合简单脚本) - 确认某个模块是否被 replace:
go list -m -f '{{.Replace}}' github.com/sirupsen/logrus,返回<nil></nil>表示没替换 - 查某模块是否在构建中实际参与:
go list -f '{{.Deps}}' ./... | grep -q 'github.com/bad/pkg' && echo "used"(需结合包级依赖检查)
注意:go list -m all 不反映条件性 require(如 // +build ignore 影响的 import),仅基于 go.mod 静态声明。
用 govulncheck 扫已知 CVE(Go 1.21+ 内置)
不是“依赖分析”工具,但它是唯一能精准关联漏洞与实际调用路径的轻量级扫描器。它不报所有版本问题,只报你代码里真用到、且该函数路径存在 CVE 的情况,误报率极低。
直接运行:govulncheck ./。输出含漏洞 ID(如 CVE-2023-1234)、影响版本范围、修复建议版本,并附带可点击的原始报告链接。
容易踩的坑:
- 旧版 Go(go install golang.org/x/vuln/cmd/govulncheck@latest
- 只扫当前构建路径下的包,
govulncheck ./...比./更全,但别扫vendor/目录(会重复或失效) - 它不检测硬编码密钥、不安全 crypto 调用等代码级问题——那是
gosec的事,不是它的职责
真正复杂的是间接依赖里的漏洞。govulncheck 能定位到 A → B → C → vuln.Foo 这条链,但不会告诉你 B 是否可升级、C 是否已弃坑。这时候得切回 go list -m -u all 和人工核查维护状态。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











