使用”go install”命令自动适配应用程序的版本信息【Go 1.16+】
使用go install命令来显示Go应用的版本
我想将我的Go语言(以下简称为Golang)应用程序添加版本信息显示的功能。
在使用自家制作的Golang应用程序中显示版本信息时,通常需要将版本信息嵌入到源代码中或在构建时通过选项传递。
如果在源代码中嵌入版本信息,可能会遇到更新繁琐或者遗忘更新的问题。因此,我们会在构建脚本等工具中读取通过git tag命令打的标签,并将其传递给构建时的参数,以解决这个问题。
然而,如果在构建时通过参数传递版本号,那么问题就出现在用 go install 安装后无法体现版本的变动。
换句话说,即使是通过 “go install” 进行安装,我也希望应用程序的版本信息能够跟随 git 标签。
顺便提一下,如果您想要批量更新使用 go install 安装的 Golang 应用程序,可以使用 gup 命令,非常方便。
github.com/nao1215/gup @ GitHub
gup: go installしたバイナリの一括アップデートコマンド(仕様と今後) @ Zenn
TL; DR (北産業) 簡而言之
-
- 通过 `debug.ReadBuildInfo` 可以在构建时获取 git 标签。
示例如果在 git tag 等中标记版本,则可以在应用程序被 `go install` 安装时与存储库的版本保持一致(不包括 `go build`)。
main.go
package main
import (
“flag”
“fmt”
“runtime/debug”
)
// Version 是应用程序在构建时通过 `-ldflags` 传递的版本信息。
var Version string
func main() {
var versionFlag = flag.Bool(“version”, false, “”)
flag.Parse()
if *versionFlag {
// 用于 “go build” 时的版本兼容性(传统方式,需要使用 LDFLAGS)
if Version != “” {
fmt.Println(Version)
return
}
// 用于 “go install” 时的版本兼容性
if buildInfo, ok := debug.ReadBuildInfo(); ok {
// 从克隆的 VCS 的最新标签获取,因此在本地的情况下会默认设置为 “(devel)”。
fmt.Println(buildInfo.Main.Version)
return
}
fmt.Println(“(unknown)”)
return
}
fmt.Println(“Hello, world!”)
}
示例存储库:https://github.com/KEINOS/go-version-opt-example/ @ GitHub
尝试在线使用 `go install` 安装上述内容并查看版本显示结果 @ paiza.IO
必需条件
在 git 或其他 VCS 中,用 “vX.Y.Z” 格式给版本标签打上标签。
将源代码适应模块模式。(放置 go.mod 和 go.sum)
只有在使用 `go install` 安装包时才会生效。因此,用于生成发布二进制文件或测试的 `go build` 不会生效。使用 `go build`,通常还是需要指定 LDFLAGS 选项(例如 `go build -ldflags=”-X main.Version=$(git describe –tags)”`)来构建基础内容。(在 Go 1.18 中可能会有改进)
兼容的 Go 版本
对于在 go.mod 中设置为 1.16 或更高版本的包来说较好。
如果 go.mod 是 1.17,则可以确保兼容性,因此推荐使用。
技巧
git タグによるバージョン情報の取得コマンド
git describe –tag
git のコミット ID の取得コマンド
git rev-parse –short HEAD
バージョン情報をビルド時に渡す例
TAG_APP=$(git describe –tag)
REV_APP=$(git rev-parse –short HEAD)
VER_APP=”${TAG_APP}+${REV_APP}”
go build -ldflags=”-s -w -extldflags \”-static\” -X ‘main.versionApp=${VER_APP}'”
文献引用
ReadBuildInfo() | debug | runtime @ pkg.go.dev
#29228: runtime/debug: document BuildInfo.Main.Version == “(devel)” | Issue | golang @ GitHub
#29814: cmd/go: use version control to discover the main module’s version? | Issue | golang @ GitHub
#172: Add go1.12 versioning support | Pull Request | golang-migrate @ GitHub