go list -m all 不显示全部依赖,因为它只列出静态声明的模块(含直接和间接依赖),不展开 vendor/ 或 replace 中的实际路径,且默认忽略测试文件、条件编译分支及未被实际 import 的模块;要获取完整依赖图,需用 go list -m -deps all、go mod graph 和 go mod why -m 组合分析。

go list -m all 为什么显示的不是全部依赖?
它只列出直接和间接模块,但不展开嵌套在 vendor/ 或 replace 中的路径。更关键的是,go list -m all 默认跳过那些被 replace 覆盖、或未被当前构建路径实际引用的模块——比如某个测试专用依赖只在 _test.go 文件里 import,而你运行的是 go list -m all(非 go list -m -deps all),它就不会出现。
真正要摸清“所有可能被加载的代码”,得组合使用:
-
go list -m -deps all:强制展开完整依赖图,包括测试和未激活的条件编译分支 -
go mod graph:输出原始依赖关系边,能一眼看出哪个模块拉入了过时的golang.org/x/cryptov0.0.0-2019xx... -
go mod why -m github.com/some/oldpkg:定位某旧模块为何还在树里,常发现是某个中间包没升级导致的“拖油瓶”
govulncheck ./ 扫不出漏洞?先检查这三件事
govulncheck 不是万能扫描器,它依赖 Go 官方漏洞数据库(vuln.golang.org),而这个库只收录已确认、已分配 CVE 的问题。很多“过时但无 CVE”的风险(比如用废弃的 crypto/bcrypt 替代方案、硬编码弱哈希算法)它根本不会报。
常见漏检原因:
- 项目用了
GOOS=js或build tags分支,而govulncheck默认只分析主构建路径 -
go.sum里存在多个版本哈希(比如同一模块 v1.2.0 和 v1.5.0 同时存在),工具可能选错基准版本比对 - 你本地
GOPROXY指向私有代理,而该代理未同步最新漏洞元数据(需确认代理是否透传vuln.golang.org查询)
补救办法:加 -os linux -arch amd64 显式指定目标平台,并用 go env -w GOPROXY="https://proxy.golang.org,direct" 临时切回官方源再跑一次。
go get -u 升级失败?别硬刚,先看 go.mod 里的 require 行
go get -u 常卡住,不是网络问题,而是模块本身有冲突约束。比如 go.mod 里同时写了:
require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/sessions v1.2.1
)
而 sessions v1.2.1 内部 require 的 mux 是 v1.7.0,这时 go get -u github.com/gorilla/mux 就会拒绝升级——因为会破坏 sessions 的兼容性承诺。
正确做法是:
- 先运行
go list -m -u all,看哪些模块标了[newest],优先升这些“无冲突候选” - 对有冲突的模块,用
go get github.com/gorilla/sessions@v1.3.0先升上游,再升下游 - 如果上游长期不维护(如
github.com/oldlib/xyz最后 release 是 2020 年),直接replace github.com/oldlib/xyz => github.com/fork/xyz v1.0.0,并确保 fork 已修复已知漏洞
go mod tidy 清不掉旧模块?它其实很保守
go mod tidy 只删除“当前代码完全没 import”的模块,哪怕那个模块被 go.mod 里 require 了,只要某处还留着 import _ "github.com/old/pkg"(空导入用于 init),它就永远在依赖树里。
更隐蔽的情况:
- 某个
.go文件被// +build ignore标记,但里面 import 了旧包,tidy仍会保留它 - vendor/ 目录存在且启用(
GOFLAGS="-mod=vendor"),tidy不会碰 vendor 里的内容,只管go.mod -
replace指向一个本地路径,而该路径下go.mod里又 require 了旧模块,tidy会递归处理,但容易漏掉子模块的子模块
彻底清理的底线操作:删掉 vendor/,设 GOFLAGS="",运行 go mod edit -droprequire github.com/old/pkg(手动删 require 行),再 go mod tidy ——但务必先 git diff go.mod 确认没误删真实依赖。
过时依赖真正的危险不在版本号本身,而在它携带的 transitive 依赖链里那些没人维护的 golang.org/x/ 子模块。最稳妥的做法不是追求“全部升到 latest”,而是用 go list -m -json all | jq -r '.Path + "@" + .Version' 导出全量清单,逐个查它们的 GitHub star 数、最近 commit 时间、是否有 open CVE ——自动化脚本可以写,但人工判断绕不开。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











