question
Generally speaking, open source software that does slightly better have version information on its binary files, such as Docker, you can view it through the following command:
$ docker --version Docker version 20.10.17, build 100c701 $ docker version ... //The output is too long,I won't show it here
Some web applications also provide a /version interface, which you can obtain through:
$ curl http://127.0.0.1:8080/version | jq { "Build Time": "Fri, 16 Jun 2023 16:19:23 +0800", "Git Commit": "b554659", "Go Version": "go1.19", "OS/Arch": "darwin/amd64", "version": "0.9.2" }
However, many companies do not have mandatory norms in this regard, and most developers do not have such awareness or habits, so most projects do not implement this function. If the binary file does not contain version information, you may have to use other systems to query or trace it. This is undoubtedly a discomfort and is not friendly to code debugging and problem positioning.
So, how to implement this function in Golang?
Ideas
There are many version information, such as code version number, Git submission number, compilation time, Go version number, etc. How to get the binary file to bring this information?
Hard code is definitely not possible in code. Because the Git commit number is generated when the code is submitted to the code repository, the Go version number and compilation time can only be obtained at compile time.
A more reasonable approach is to inject it at compile time. The Go compilation tool provides the -ldflags option, which can inject the value of the package variable through the -X parameter. We only need to define the version information as the package variable in the code, and then complete the injection at compile time. This process can be implemented as automated, and the following is an example of the make tool.
Implementation steps
1. Define the variables for version information in the code
Define the code version number, Git commit number, and compile time as package variables:
package config var ( Version string //Code version number GitCommit string //Git submission number BuildTime string //Compilation time)
Go version number and other information can be obtained with the help of the runtime package:
() //Go version //operating system //Platform architecture
2. Use these variables in your code
1) Implement --version parameters or version subcommand
byCobraAs an example, the command line framework implements the --version parameter for rootCmd:
= ((`{{with .Name}}{{printf "%%s version information: " .}}{{end}} {{printf "Version: %%s" .Version}} Git Commit: %s Build Time: %s Go version: %s OS/Arch: %s/%s `, , , (), , ))
2) Implement/version interface
byGinAs an example, route /version to the following Version function:
func Version(ctx *) { ().Set("Content-Type", "application/json") () ().Encode(map[string]string{ "version": , "Git Commit": , "Build Time": , "Go Version": (), "OS/Arch": + "/" + , }) }
3. Get version information before compilation
In Makefile, use the git command to get the code version number and Git submission number, and use the date command to get the current time
VERSION = $(shell git describe --tags --always) GIT_COMMIT = $(shell git rev-parse --short HEAD) BUILD_TIME = $(shell date -R)
4. Inject version information at compile time
In Makefile, use the -ldflags option to pass in the compile parameters to the go build command to implement the injection of version information
define LDFLAGS "-X '/myname/myapp/=${VERSION}' \ -X '/myname/myapp/=${GIT_COMMIT}' \ -X '/myname/myapp/=${BUILD_TIME}'" endef build: go build -ldflags ${LDFLAGS} -o myapp_${VERSION} .
5. Verify the effect
Compile the binary and verify the --version parameter; start the service process with binary and verify the /version interface.
$ make build ... //Compilation process, omit output$ myapp --version myapp version information: Version: 0.9.2 Git Commit: b554659 Build Time: Sat, 17 Jun 2023 11:30:44 +0800 Go version: go1.20.5 OS/Arch: darwin/arm64 $ myapp ... //Start the process and omit the output$ curl http://127.0.0.1:8080/version | jq { "Build Time": "Sat, 17 Jun 2023 11:30:44 +0800", "Git Commit": "b554659", "Go Version": "go1.20.5", "OS/Arch": "darwin/arm64", "version": "0.9.2" }
Summarize
The binary file is directly equipped with version information, which can bring great convenience to code debugging and problem positioning. This article introduces the specific practices of injecting version information at compile time through the -ldflags option.
This is a relatively general method, many open source software such asDockerThis is also done.
This is the end of this article about how Golang injects version information during compilation. For more information about Golang compilation and injection, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!