起因是这样的,在编译发布 golang 工程时,希望版本号中包含有 git revision number。 但是,没有commit之前,是没法知道 revision number 的,commit之后,如果要修改代码中 version 的相关信息,又会导致需要再次的 commit。
针对这种情况,希望能够在编译时动态的将当前的 git revision number 加入到 version 中。 这样,每次编译的时候获取当前 revision number,写入编译完的 二进制中,可以避免现有的代码(修改现有代码会导致又需要 commit)。
注 revision number 就是每个 commit 对应的 唯一字符串。
实现方式实现的原理很简单:在 golang 编译时,通过 ldflags 给代码中的变量赋值,达到注入 revision number 的目的。
示例代码package main import "fmt" import "flag" var ( version = "v0.0.1" build = "not set" ) func main() { var v = flag.Bool("v", false, "display version") flag.Parse() if *v { fmt.Printf("version: %s\n", version) fmt.Printf("build : %s\n", build) } else { fmt.Println("hello, test version") } }
上面的代码编译运行,效果如下:
$ go build main.go $ ./main hello, test version $ ./main -v version: v0.0.1 build : not set
编译时修改 build 变量通过 ldflags, 动态修改 build
$ go build -ldflags "-X main.build=`git rev-parse HEAD`" main.go $ ./main -v version: v0.0.1 build : 23af559af14a0b83c35a7f8bd0670a9741b1dc7e
-X main.build 修改 main package 中的 build 变量
`git rev-parse HEAD` 获取当前的 git revision number
总结动态注入版本号,避免了手动修改版本号而导致的再次 commit,也避免了手动操作的繁琐和错误。 为了方便使用,也可以把上面的编译命令封装到 makefile 或者某个编译脚本中。