Go 的版本自动化
一般情况下,我会在发布程序时把编译的时期附在版本号里,按照 semver 的规则,一个版本号会是这样子:0.1.2+20161129
,前三个字符相对来说改动比较少,但是最后的日期一天一变,如果采用手动改变代码中常的方式,就比较得麻烦。所以我会使用 shell 和 go build
命令的 ldflags
参数相结合,在每次编译时,自动更新这个个变量。
下面是一段简单的代码,用来作为示例,除了编译日期之外,还指定了一个 commit hash,用于记录最后的提交 ID:
1// Copyright 2016 by caixw, All rights reserved.
2// Use of this source code is governed by a MIT
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8 "flag"
9)
10
11const mainVersion = "1.2.3"
12
13var (
14 buildDate string
15 commitHash string
16)
17
18func main() {
19 v := flag.Bool("v", false, "显示版本号")
20 flag.Parse()
21
22 if *v {
23 version := mainVersion
24 if len(buildDate) > 0 {
25 version += "+" + buildDate
26 }
27 fmt.Println("version:", version)
28
29 if len(commitHash) > 0 {
30 fmt.Println("git commit hash:", commitHash)
31 }
32 return
33 }
34
35 // TODO
36}
下面是相对应的一个简单 shell 脚本,用于编译代码:
1# 获取两个参数变量,等号两端不要有空格
2buildDate=$(date -u '+%Y%m%d')
3hash=$(git rev-parse HEAD)
4
5go build -ldflags "-X main.buildDate=${buildDate} -X main.commitHash=${hash}"
执行 ./main
,将会输出类似以下内容:
1version:1.2.3+20161129
2git commit hash: 8b3632a2451edcd175939de6581315b9dde0fbd7
关于 ldflags 参数:
- 不能修改常量,只能是变量;
- 变量可以小写;
- 若不是 main 包,则需要指定全路径:
go build -ldflags="-X github.com/caixw/gobuild/vars.xxx=$(date -u '+%Y%m%d')"
; - 可以同时指定多个,采用
"-X importpath.name=xxx -X importpath.name=XXX"
的形式。