在实际开发中,当开发完一个 apiserver 特性后,会编译 apiserver 二进制文件并发布到生产环境,很多时候为了定位问题和出于安全目的(不能发错版本),我们需要知道当前 apiserver 的版本,以及一些编译时候的信息,如编译时 Go 的版本、Git 目录是否 clean,以及基于哪个 git commmit 来编译的。在一个编译好的可执行程序中,我们通常可以用类似 ./app_name -v
的方式来获取版本信息。
我们可以将这些信息写在配置文件中,程序运行时从配置文件中取得这些信息进行显示。但是在部署程序时,除了二进制文件还需要额外的配置文件,不是很方便。或者将这些信息写入代码中,这样不需要额外的配置,但要在每次编译时修改代码文件,也比较麻烦。Go 官方提供了一种更好的方式:通过 -ldflags -X importpath.name=value
(详见 -ldflags -X importpath.name=value)来给程序自动添加版本信息。
1.增加参数-v
package main import ( "encoding/json" "fmt" "os" ... v "apiserver/pkg/version" ... ) var ( version = pflag.BoolP("version", "v", false, "show version info.") ) func main() { pflag.Parse() if *version { v := v.Get() marshalled, err := json.MarshalIndent(&v, "", " ") if err != nil { fmt.Printf("%v\n", err) os.Exit(1) } fmt.Println(string(marshalled)) return } ... }
pkg/version包中的实现:
base.go
package version // 变量通过-ldflags -X importpath.name=value在编译时传入程序中 var ( gitTag = "" // gitBranch = "" gitCommit = "$Format:%H$" gitTreeState = "not a git tree" buildDate = "1970-01-01T00:00:00Z" )
version.go
package version import ( "fmt" "runtime" ) type Info struct { GitTag string `json:"gitTag"` GitBranch string `json:"gitBranch"` GitCommit string `json:"gitCommit"` GitTreeState string `json:"gitTreeState"` BuildDate string `json:"buildDate"` GoVersion string `json:"goVersion"` Compiler string `json:"compiler"` Platform string `json:"platform"` } func (info Info) String() string { return info.GitTag } func Get() Info { return Info{ GitTag: gitTag, GitBranch: gitBranch, GitCommit: gitCommit, GitTreeState: gitTreeState, BuildDate: buildDate, GoVersion: runtime.Version(), Compiler: runtime.Compiler, Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), } }
其中的gitTag, gitBranch,gitComit,gitTreeState,buildDate信息都是在build的时候, 使用-ldflags -X key=value的方式指定参数
Makefile文件中:
.PHONY: all build windows mac run tidy check cert test cover lint docker clean help BIN_FILE=golang-demo MAIN_FILE=./cmd/app/main.go SHELL := /bin/bash BASEDIR = $(shell pwd) # build with verison infos versionDir = "golang-demo/pkg/version" ## 获取仓库tag gitTag = $(shell if [ "`git describe --tags --abbrev=0 2>/dev/null`" != "" ];then git describe --tags --abbrev=0; else git log --pretty=format:'%h' -n 1; fi) buildDate = $(shell TZ=Asia/Shanghai date +%FT%T%z) gitCommit = $(shell git log --pretty=format:'%H' -n 1) gitTreeState = $(shell if git status|grep -q 'clean';then echo clean; else echo dirty; fi) gitBranch = $(shell git rev-parse --abbrev-ref HEAD) ldflags="-w -X ${versionDir}.gitTag=${gitTag} -X ${versionDir}.buildDate=${buildDate} -X ${versionDir}.gitBranch=${gitBranch} -X ${versionDir}.gitCommit=${gitCommit} -X ${versionDir}.gitTreeState=${gitTreeState}" # 默认执行 all: build # 打包成二进制文件 build: tidy check @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags $(ldflags) -o $(BIN_FILE)_linux $(MAIN_FILE) windows: tidy check @CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -v -ldflags "-w -s" -o $(BIN_FILE)_windows.exe $(MAIN_FILE) mac: tidy check @CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -ldflags "-w -s" -o $(BIN_FILE)_darwin $(MAIN_FILE) # 启动服务 run: @go run $(MAIN_FILE) -c ./config/config.yaml tidy: @go mod tidy # 代码验证 check: @gofmt -s -w ./ @go vet $(MAIN_FILE) cert: @openssl req -new -nodes -x509 -out config/server.crt -keyout config/server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=127.0.0.1/[email protected]" # 单元测试 test: @go test ./... # 覆盖测试 cover: @go test -coverprofile xx.out @go tool cover -html=xx.out lint: @golangci-lint run --enable-all docker: @docker build -t golang-demo:latest . clean: @go clean -x rm -f "xx.out" help: @echo "make - 格式化go代码 并编译生成二进制文件" @echo "make test - 执行测试case" @echo "make check - 代码检查" @echo "make cover - 检测测试覆盖率" @echo "make run - 启动服务" @echo "make lint - 执行代码检查" @echo "make docker - 生成Docker镜像" @echo "make clean - 清理中间目标文件" @echo "make build - 编译成二进制文件(默认:Linux)" @echo "make windows - 编译成二进制文件(Windows)" @echo "make mac - 编译成二进制文件(Mac)" # include ./TestMakefile 包含其他Makefile
-w: 去除调试信息, 无法使用gdb调试, 但是二进制文件更小
执行./golang-demo -v
{ "gitTag": "d62a870", "gitBranch": "master", "gitCommit": "d62a87056066b2f8ecf6caf64b3bd1d80d60a5e1", "gitTreeState": "dirty", "buildDate": "2023-08-24T17:10:45+0800", "goVersion": "go1.20.7", "compiler": "gc", "platform": "linux/amd64" }
标签:功能,string,make,echo,golang,json,version,go,版本信息 From: https://www.cnblogs.com/xingxia/p/golang_version.html