Go项目用goreleaser做多版本发布,核心是Git tag触发+正确配置builds和archives,而非手动改配置切版本;goreleaser默认只发当前annotated tag对应版本,因{{.Version}}源自tag且不支持多tag单次发布。

直接说结论:Go 项目用 goreleaser 做多版本发布,核心不是“怎么配多个 version”,而是靠 Git tag 触发 + 正确配置 builds 和 archives,让同一份配置能适配不同语义化版本(如 v1.2.3、v2.0.0)自动产出对应产物。手动改配置文件来切版本是反模式。
为什么 goreleaser release 默认只发当前 tag 版本
goreleaser 的设计逻辑是“一次 release 对应一个 Git tag”。它启动时会自动从最近的 annotated tag(比如 git tag -a v1.2.3 -m "release")读取 {{ .Version }},所有模板变量(如 name_template、ldflags)都基于这个值展开。不打 tag,goreleaser release 会报错 no git tag found;打多个 tag,得分别执行多次命令。
- Git 必须使用 annotated tag(
git tag -a),lightweight tag(git tag)会被忽略 - tag 名必须符合语义化版本格式,如
v1.2.3、v2.0.0-rc.1;1.2.3或release-v1不会被识别为版本号 - 本地测试多版本时,可用
goreleaser release --snapshot --rm-dist跳过 tag 校验,但 CI 中必须依赖真实 tag
builds 怎么写才能让 v1 和 v2 都正确构建
关键在 builds[].main 和 builds[].binary 不能硬编码版本号——它们决定编译入口和输出名,跟 Git tag 无关;而 ldflags 注入的版本信息才动态绑定 {{ .Version }}。
-
builds[].main: ./cmd/myapp/main.go—— 指向固定路径,v1/v2 共用同一入口 -
builds[].binary: myapp—— 输出二进制名不含版本,避免myapp-v1.2.3这种冗余;版本体现在归档名里更合理 -
builds[].flags: ["-ldflags=-X main.version={{.Version}}"]—— 这才是让运行时myapp --version输出正确值的关键 - 如果 v1 和 v2 的 main 入口不同(比如 v2 拆了 CLI 到新目录),就该拆成两个独立仓库或用 Go module 多 module 管理,而不是塞进一个
.goreleaser.yaml
archives.name_template 控制用户看到的下载文件名
GitHub Release 页面上用户点下载的不是原始二进制,而是 archives 打包后的压缩包。这个文件名直接影响体验,必须用模板动态嵌入 {{ .Version }},且做系统名映射。
立即学习“go语言免费学习笔记(深入)”;
- 别用默认的
{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }},因为{{ .Os }}输出darwin,不是用户认知里的macos - 推荐写法:
name_template: "{{ .ProjectName }}-v{{ .Version }}-{{ if eq .Os \"darwin\" }}macos{{ else }}{{ .Os }}{{ end }}-{{ .Arch }}" - Windows 用户需要
.exe后缀?加到归档内主程序名里:files: ["dist/{{ .ProjectName }}{{ if eq .Os \"windows\" }}.exe{{ end }}"],或用replacements统一处理 - 想同时提供
.tar.gz和.zip?设archives.formats: [tar.gz, zip],并确保两个模板都含{{ .Version }}
多版本共存时 checksum 和签名容易踩的坑
每个版本 release 都要生成独立的 checksums.txt 和签名文件,否则老版本文件会被覆盖,下游校验失败。
-
checksums.name_template必须包含{{ .Version }},例如:"{{ .ProjectName }}_{{ .Version }}_checksums.txt" -
signs块默认关闭,启用后需配cmd: gpg和args;签名文件名也受name_template控制,同样要带版本 - 如果项目长期维护多个大版本(如 v1.x、v2.x),建议在 GitHub Release 的
footer或changelog里加说明,避免用户误升级
最常被忽略的一点:跨平台构建漏组合不是“少几个包”,而是 Windows 用户根本下不到 .exe,ARM macOS 用户打不开二进制——这些必须在 builds 里显式列全 goos/goarch 笛卡尔积,不能依赖默认值。


















