在 Golang 的二进制文件中嵌入版本信息 #golang
在之前的文章中,我们使用了 Golang 和 Line Notify 来创建了一个检查 API 证书过期日期的功能。但是这次我们将添加版本号到已创建的二进制文件中。
简要描述
我打算写下粗略调查的结果和想做的事情。
-
- Golang でビルドしたバイナリはデフォルトでバージョンが埋め込まれるわけではない
「main.go」などに変数を用意してビルド時などに埋め込む必要がある
ビルド時のオプションで変数に値を設定可能
「flag」パッケージを利用して、オプションの処理を実装する必要がある
バージョンはバージョン番号とリビジョンに分けて管理
バージョンは git の最新のタグを利用(v1.0.0 なイメージ)
リビジョンは git の最新のタグのショートリビジョンを利用(e5a4228なイメージ)
源代码
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
"time"
)
var version = "unknown"
var revision = "unknown"
func main() {
var endpoint = flag.String("endpoint", "", "check target Endpoint URL")
var lineToken = flag.String("token", "", "LINE notify token")
var showVersion = false
flag.BoolVar(&showVersion, "v", false, "show application version")
flag.BoolVar(&showVersion, "version", false, "show application version")
flag.Parse()
if showVersion {
fmt.Println("version(", version+"."+revision, ")")
} else {
var apiResult = getAPI(*endpoint)
var result = postLINE(*lineToken, apiResult)
fmt.Printf("LINE Post result [%t]\n", result)
}
}
func getAPI(endpoint string) string {
if endpoint == "" {
log.Println("not endpoint")
return "not endpoint"
}
var result = ""
resp, err := http.Get(endpoint)
if err != nil {
result = fmt.Sprintf("NG\n%s", err)
} else {
defer resp.Body.Close()
expire := "-"
if len(resp.TLS.PeerCertificates) > 0 {
expireUTCTime := resp.TLS.PeerCertificates[0].NotAfter
expireJSTTime := expireUTCTime.In(time.FixedZone("Asia/Tokyo", 9*60*60))
expire = expireJSTTime.Format("06/01/02 15:04")
}
result = fmt.Sprintf("OK (expire=%s)\n%s", expire, endpoint)
}
return result
}
func postLINE(token string, message string) bool {
if token == "" {
log.Println("not token")
return false
} else if message == "" {
log.Println("not text")
return false
}
data := url.Values{"message": {message}}
r, _ := http.NewRequest("POST", "https://notify-api.line.me/api/notify", strings.NewReader(data.Encode()))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
resp, err := http.DefaultClient.Do(r)
if err != nil {
log.Println(err)
return false
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
return false
}
return true
}
通过git命令获取最新标签的短版本和哈希值。
获取最新的标签
$ git describe --tags --abbrev=0
v1.0.0
获取哈希值的简短版本
$ git rev-parse --short HEAD
e5a4228
在构建时嵌入版本和修订号
通过在构建go文件时使用ldflags选项,可以为go文件中定义的变量设置值。
建筑
$ GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.version=$(git describe --tags --abbrev=0) -X main.revision=$(git rev-parse --short HEAD)"
版本检查
$ ./apichecker -v
version( v1.0.0.e5a4228 )
总结
如果长期使用命令行工具,就会不知道正在使用的是哪个版本的二进制文件,所以我觉得应该养成一个必须嵌入版本的习惯。
不过,由于经常使用,所以我认为将其作为标准功能实现会更方便。
附录
- ソースコード