go list 是查询工具而非包管理器,仅检索已存在模块和包信息;需在含 go.mod 的模块根目录执行,配合 -m、-json 等标志及正确路径才能准确获取依赖列表、版本、导入关系等。

go list 不是包管理器,它不安装、升级或锁定依赖,只查询已存在的模块和包信息——误把它当 npm list 或 pip show 用,八成会卡在空输出或报错上。
为什么 go list 经常返回空或 “no Go files”
常见于当前目录不含 .go 文件,或未在模块根目录下执行。Go 要求必须处于一个有效的 module 内(即存在 go.mod),且目标包路径需能被解析为实际存在的 Go 包。
- 先运行
go mod init example.com/foo初始化模块(如果还没做) - 确保至少有一个
.go文件,哪怕只是空的package main - 查本地包时用相对路径:例如
go list ./...,不是go list .(后者只查当前目录,不含子包) - 查标准库用完整导入路径:
go list fmt,不能写go list /fmt
常用模式:列出所有直接依赖模块
想看 go.mod 里 require 块中声明的模块(不含 transitive 依赖),得加 -m 标志,并配合 -f 控制输出格式:
go list -m -f '{{.Path}} {{.Version}}' all
注意:all 在这里不是通配符,而是 go list -m 的特殊参数,表示“所有已知模块”。若只想看直接依赖,用:
立即学习“go语言免费学习笔记(深入)”;
go list -m -f '{{if not .Indirect}}{{.Path}} {{.Version}}{{end}}' all
-
.Indirect字段为true表示该模块是间接引入的(即没出现在go.mod的require中) - 不加
-f会输出大量 JSON 风格结构体,不适合人眼阅读 -
go list -m不检查包代码是否存在,所以即使某个模块没下载也能列出来(此时.Version可能为空)
查某个包的依赖树(非官方,但实用)
go list 本身不提供类似 npm ls 的树形输出,但可通过组合 -f 模板 + 递归调用逼近效果:
go list -f '{{.ImportPath}}: {{join .Deps " "}}' net/http
这会打印 net/http 直接 import 的所有包路径。若要展开一层依赖,可对每个 .Deps 再跑一次 go list ——但注意,.Deps 列出的是编译期依赖,不含条件编译(如 // +build ignore)或测试专用依赖(_test 后缀包)。
-
.Deps不包含标准库隐式依赖(如unsafe、internal/bytealg) - 跨平台构建时,
.Deps结果可能因GOOS/GOARCH不同而变化 - 想查测试依赖?得显式加
-test参数:go list -test -f '{{.TestImports}}' package/path
容易忽略的细节:-json 输出与工具链集成
脚本化处理时,优先用 -json 而非自定义 -f,因为字段稳定、易解析:
go list -json -m all | jq 'select(.Indirect == false) | .Path'
但要注意:go list -json 对每个包单独输出一行 JSON(NDJSON),不是单个 JSON 数组,jq 需配合 --slurp 或逐行处理。
-
-json模式下,错误不会终止整个命令,而是以{"Error":{...}}形式混在输出流中 - 某些字段如
.Module在非 module 模式下为 null,别假设它总存在 - Windows 上路径分隔符在
.Dir字段中仍是正斜杠(Go 内部统一处理),勿硬匹配反斜杠
真正难的不是记住命令,而是理解 go list 的视角:它始终站在“当前构建配置”下看包,而这个配置由 go.mod、当前工作目录、环境变量(GOOS 等)、甚至 go build 的隐式参数共同决定——换一个条件,结果就可能不同。










