概述
今天在查一个很久之前运行的程序的问题,结果发现自己根本不知道那个代码是什么时候,用什么版本代码编译的,导致查找问题时异常困难。所以以后写代码时,很有必要将相关编译信息加入到程序中,这样在某些时候,查找问题会方便很多,避免低级错误。
编译时加入自定义信息到程序中
通常情况下,我们直接使用go build
来编译程序,要想加入自定义信息到程序中,很简单,编译时使用-ldflags
就行。
例如有如下程序test.go:
1 | package main |
在编译时加入-ldflags
:
1 | go build -ldflags "-X 'main.AAA=111' -X 'main.BBB=222'" |
运行程序:
1 | ./test |
可以看到AAA和BBB两个变量的值变成了111和222,也就是在编译时加入的信息。
文档中可以看到相关参数的说明:
hdr-Compile_packages_and_dependencies
1 | -ldflags '[pattern=]arg list' |
这里的importpath.name=value
可以理解为包名.变量名
,比如上面的main.AAA
就表示main包下的AAA变量。
编译时加入git信息等到程序中
在上面已经叙述了如何加入自定义信息到程序中,所以只要在编译时先获取到相关git信息,然后通过ldflags来加入到程序中即可。
test.go代码如下:
1 | package main |
编译时使用如下命令:
1 | go build -ldflags "-X 'main.Version="v0.1.1"' -X 'main.GoVersion=`go version`' \ |
其中:
go version
:获取到编译使用的go版本信息。git remote -v
:获取到当前远程仓库的地址。git rev-parse --abbrev-ref HEAD
:获取到当前分支名。git rev-parse HEAD
:获取到当前代码的commit号。git describe --tags --abbrev=0
:获取到最近的tag。date +"%Y-%m-%d %H:%M:%S %Z"
:获取当前编译时间。
运行程序,打印结果如下:
1 | ./test |
这样就达到了目的。
使用Makefile来进行编译
注意到刚才编译时的命令:
1 | go build -ldflags "-X 'main.Version="v0.1.1"' -X 'main.GoVersion=`go version`' \ |
如果每次编译时,都要手动输入这么一大串……不可能的事情
可以使用Makefile来简化这个过程,在项目中新建Makefile文件,内容如下:
1 | VERSION="v0.1.1" |
这里CGO_ENABLED=0 GOOS=linux GOARCH=amd64
用于指定代码运行平台(交叉编译),其中:
CGO_ENABLED=0
:表示不启用cgo。GOOS=linux
:表示为linux平台编译代码。GOARCH=amd64
:表示代码执行架构为amd64。
然后编译时,直接使用make
即可:
1 | make |
其中all
后面跟着的子模块就代表make时会执行的子模块,比如all: build1 build2
那么make时就会执行build1和build2两个模块。也可以使用make build
,这样就只会执行build子模块。
注意这里-X 'main.GoVersion=${GO_VERSION}'
中还要加两个引号,是因为go version
执行的结果中会包含空格,如果不加引号make会报错,索性这里全部加上了引号。
顺便在程序启动时打印一个字符画
1 | package main |
效果如下:
1
2
3
4
5
6
__ __ ____ _ _
| \/ | _ _ | _ \ _ __ ___ (_) ___ ___ | |_
| |\/| | | | | | | |_) | | '__| / _ \ | | / _ \ / __| | __|
| | | | | |_| | | __/ | | | (_) | | | | __/ | (__ | |_
|_| |_| \__, | |_| |_| \___/ _/ | \___| \___| \__|
|___/ |__/
1 | __ __ ____ _ _ |
程序启动时的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
=====================================================================
__ __ ____ _ _
| \/ | _ _ | _ \ _ __ ___ (_) ___ ___ | |_
| |\/| | | | | | | |_) | | '__| / _ \ | | / _ \ / __| | __|
| | | | | |_| | | __/ | | | (_) | | | | __/ | (__ | |_
|_| |_| \__, | |_| |_| \___/ _/ | \___| \___| \__|
|___/ |__/
=====================================================================
=====================================================================
Version: v0.1.1
Go Version: go version go1.15.5 linux/amd64
Git URL: origin https://xxx.git (fetch)
origin https://xxx.git (push)
Git Branch: master
Git Commit: 71c8xxxxxxxx21b
Git Latest Tag: v0.1.1
Build Time: 2021-07-15 09:07:19 CST
=====================================================================
1 | ===================================================================== |
部分问题
使用goland在编写Makefile时会出现格式错误:
由于Makefile规定缩进必需是tab,但是通常情况下我们把golang的tab改成了4个空格,这就导致用goland写的Makefile有格式错误。
一个简单的解决方法,下载Makefile插件即可:
插件安装之后重启goland,然后在编辑Makefile时,tab就会强制变为“tab”而不是4个空格。
make时出现version "go1.14" does not match go tool version "go1.15.5"
:
出现这个错误,可能是因为当前环境中的go版本与系统的go版本不一致造成的:
1 | type go |
可以看到系统的go版本是1.15.5的,与当前环境的go1.14不一致。解决这个问题,只要让版本一致,或者删掉其中一个go环境就好了。
我这里直接把当前环境的go也升级到了1.15.5,就不再出现这个问题了。