go|go build -ldflags 打印编译信息

go语言方便的地方之一就是容易部署, 编译成二进制文件,丢到服务器,就像一个内建的bash程序,不用安装依赖,不用部署环境,不用管理源码,直接就运行了。这也会产生一个问题, 经过年深日久的运行后,某天需要修改一个功能,可能最初开发的同事几经易手,那么,如何从这个二进制文件找到源码和对应的信息呢?
本文主要就是解决这个问题,利用 go build 的 -ldflags -X, 把程序及相关的环境信息编译进项目的的help信息中,当程序执行-v时,有如下的输出:

$ ./bin/version-example -v BuildTime: 202104201738 BuildGitBranch: master BuildGitCommit: da06480 BuildPkgModule: version-example test ------ 202104201738-da06480

-X importpath.name=valueSet the value of the string variable in importpath named name to value. This is only effective if the variable is declared in the source code either uninitialized or initialized to a constant string expression. -X will not work if the initializer makes a function call or refers to other variables.

## 新建一个version的项目文件夹: $ mkdir version## 使用go mod 建一个 version-example 的 项目 $ go mod init version-example## 后面按照下面的目录结构建立以下几个文件 . ├── build.sh ├── go.mod ├── main.go └── version/ └── version.go

  • main.go
package mainimport ( "flag" "fmt""version-example/version" )var printVersion = flag.Bool("v", false, "show build version for the program")func main() { flag.Parse()if *printVersion { version.PrintVersion() }fmt.Println("test ------")fmt.Println(version.BuildInfo.String()) }

  • version.go
package version// 打印当前的编译信息import ( "fmt" )var ( BuildDateTime= "" BuildGitBranch= "" BuildGitCommit= "" BuildPackageModule = "" )var BuildInfo = PkgVersion{}func init() { BuildInfo = PkgVersion{ BuildGitBranch:BuildGitBranch, BuildDateTime:BuildDateTime, BuildGitCommit:BuildGitCommit, BuildPackageModule: BuildPackageModule, } }type PkgVersion struct { BuildDateTimestring BuildGitBranchstring BuildGitCommitstring BuildPackageModule string }func (r PkgVersion) String() string { return r.BuildDateTime + "-" + r.BuildGitCommit }func (m PkgVersion) PrintlnVersion() { fmt.Printf("%15s: %s \n", "BuildTime", BuildDateTime) fmt.Printf("%15s: %s \n", "BuildGitBranch", BuildGitBranch) fmt.Printf("%15s: %s \n", "BuildGitCommit", BuildGitCommit) fmt.Printf("%15s: %s \n", "BuildPkgModule", BuildPackageModule) fmt.Println() }func PrintVersion() { BuildInfo.PrintlnVersion() }

  • build.sh
#!/usr/bin/env bash ## linux codemoduleName=$(go list -m) commit=$(git rev-parse --short HEAD) branch=$(git rev-parse --abbrev-ref HEAD) buildTime=$(date +%Y%m%d%H%M)## version.go 包名 变量 versionPkgName="version"flags="-X '${moduleName}/${versionPkgName}.BuildGitBranch=${branch}' -X '${moduleName}/${versionPkgName}.BuildGitCommit=${commit}'-X '${moduleName}/${versionPkgName}.BuildDateTime=${buildTime}' -X '${moduleName}/${versionPkgName}.BuildPackageModule=${moduleName}' "program=$(basename ${moduleName})#echo "$program" # #echo "${flags}" # #echo "$(pwd)" ### GOOS=linux go build go build -o bin/$program -ldflags "$flags" -v -mod=vendormain.go

【go|go build -ldflags 打印编译信息】文件准备完成后, 执行下面的命令,把文件加入git版本管理中,如果不加git管理, build.sh中的脚本会执行报错:
git init git add .git commit -m "first commit"

现在执行build.sh 编译二进制文件,执行完成后,可见文件目录中多了一个文件 version-example
. ├── bin │└── version-example ├── build.sh ├── go.mod ├── main.go └── version └── version.go

## 打印该文件帮助 $ ./bin/version-example -h Usage of ./bin/version-example: -vshow build version for the program## 打印文件版本号 $ ./bin/version-example -v BuildTime: 202104201738 BuildGitBranch: master BuildGitCommit: da06480 BuildPkgModule: version-exampletest ------ 202104201738-da06480

    推荐阅读