go-licenses save 必须在含 go.mod 的模块根目录执行,不支持 go111module=on 隐式行为或 --modfile;需显式指定 --save_path(不以/结尾),且目标父目录须存在可写;v2 不支持旧格式参数,依赖 go.sum 完整性,不处理 replace 本地路径的许可证缺失。

go-licenses save 命令必须在模块根目录执行
直接运行 go-licenses save 会失败,除非当前工作目录下有有效的 go.mod。它不读取 GO111MODULE=on 环境变量的隐式行为,也不支持通过 --modfile 指定路径。常见错误是误在子目录或 tools/ 目录里执行,结果提示 no go.mod file found。
实操建议:
- 进入项目根目录(含
go.mod的那一层),再运行命令 - 若项目含多个模块(如 monorepo),需为每个模块单独执行,
go-licenses不自动遍历子模块 - 避免用
cd ./submodule && go-licenses save—— 这会把依赖路径误判为相对路径,导致许可证文件缺失
go-licenses v2 需要显式指定 --save_path 且路径不能以 / 结尾
go-licenses save 默认不输出任何文件,也不会创建目录。漏掉 --save_path 参数会导致静默成功但无实际输出;而路径末尾加 /(如 --save_path=./licenses/)会触发内部路径拼接错误,最终生成空目录或报错 failed to create directory: permission denied(尤其在 Docker 容器中)。
实操建议:
- 始终使用绝对路径或明确的相对路径,例如
--save_path=.licenses - 确保目标路径父目录存在且可写;
go-licenses不自动mkdir -p - v2 版本不再支持
--format=markdown等旧参数,只保留json和默认文本格式
校验失败时先检查 go.sum 是否完整,而非直接重装工具
当 go-licenses save 报错 failed to load module graph: no matching versions for query "latest" 或卡在某个依赖上,大概率不是工具问题,而是 go.sum 缺失对应模块的校验和条目。这通常发生在:go mod tidy 后未运行 go mod download,或 go.sum 被 gitignore 忽略导致未提交。
实操建议:
- 先运行
go mod verify,确认输出all modules verified - 若失败,执行
go mod download补全缓存,再重试go-licenses - 不要用
go install github.com/google/go-licenses/v2@latest在 CI 中反复安装——v2 已发布稳定版,固定版本更可靠:go install github.com/google/go-licenses/v2@v2.0.0
许可证文件名冲突需手动处理,go-licenses 不去重
go-licenses 对同名许可证(如多个包都带 LICENSE 或 MIT.txt)不做重命名或合并,而是直接覆盖写入。结果常是最后处理的那个模块的许可证“赢了”,其他被丢弃。这不是 bug,是设计如此——它只负责提取,不负责归一化。
实操建议:
- 用
--format=json输出结构化数据,再用 Python 或 jq 提取并分类:go-licenses save . --save_path=/dev/stdout --format=json | jq '.[] | select(.license == "MIT")' - 对关键依赖(如 GPL 类库),单独用
go list -m -f '{{.Dir}}' github.com/example/pkg定位源码路径,人工核对其LICENSE文件内容 - 别依赖
.licenses目录直接用于合规归档——它只是起点,仍需人工复核是否涵盖所有传递依赖的许可证
replace github.com/x/y => ../local-fork,而 ../local-fork 目录下没放许可证,go-licenses 就不会报错,也不会生成对应文件。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











