➜ code ✗ ./client -ver version is: v0.0.1dateTime is: 2021-08-14 10:00:00gitTag is: v0.0.1分析:在很多公司甚至开源项目都会采用该方式,在代码中显式地添加版本等信息。
假设不经常发版或者发版周期比较长,则完全没问题假设发版频繁,很大概率会出现版本信息的遗漏、错误假设版本信息忘记更改,则查询出来的信息就是错的针对以上情况,提出一个问题:Go是编译型语言,版本等信息是否可以在编译时,自动地打包到二进制文件中?方案2,自动打包版本信息:package mainimport ("flag""fmt")var version = "v0.0.0"// 此处暂时只填写大的版本号var gitTag stringvar dateTime stringfunc main() {debugVerInfo := flag.Bool("ver", false, "show app version info")flag.Parse()if *debugVerInfo {fmt.Println("version is:", version)fmt.Println("dateTime is:", dateTime)fmt.Println("gitTag is:", gitTag)return}fmt.Println("do other thing")}在编译时,打包版本等信息到Go的二进制文件中:go build -ldflags \"-X main.version=v0.0.1 -X main.dateTime=`date +%Y-%m-%d,%H:%M:%S` -X main.gitTag=`git tag`" \ -o clientbuild 通过 -ldflags 的 -X 参数可以在编译时将值写入变量变量格式:包名称.变量名称=值查看版本信息➜ code ✗ ./client -ver version is: v0.0.1dateTime is: 2021-08-14 10:00:00gitTag is: v0.0.1优点:无需代码中显式添加版本等信息避免手动添加版本信息时,遗漏或者错误等情况发生可使用持续集成工具自动把版本等信息打包到二进制文件中原理二进制文件在加载到内存中之后,整个内存空间会被划分为若干段。
除了代码区、数据区、堆、栈,还有有一个段为符号表。
在编译时,把版本等信息打包到符号表中,供程序运行时使用。
[root@localhost demo]# readelf -s client | grep main...... 1686: 00000000005608b0 16 OBJECT GLOBAL DEFAULT 10 main.version 1687: 00000000005608a0 16 OBJECT GLOBAL DEFAULT 10 main.gitTag 1688: 0000000000560890 16 OBJECT GLOBAL DEFAULT 10 main.dateTime...... 2320: 00000000004eb2e8 7 OBJECT GLOBAL DEFAULT 2 main.version.str 2321: 00000000004ebba0 20 OBJECT GLOBAL DEFAULT 2 main.dateTime.str 2322: 00000000004eb2e0 7 OBJECT GLOBAL DEFAULT 2 main.gitTag.str使用 readelf -s命令查看编译好的Go二进制文件符号表信息,可以明显看到在编译时写入的三个变量。
其中,main.version、main.gitTag、main.dateTime 大小都为16,是指 在Go中的string类型结构体大小。
(gdb) ptype versiontype = struct string { uint8 *str; int len;}(gdb) ptype dateTimetype = struct string { uint8 *str; int len;}(gdb) ptype gitTagtype = struct string { uint8 *str; int len;}不知细心的你是否发现,在符号表显示的变量具体值 main.version.str、main.dateTime.str、main.gitTag.str长度都比实际多一个字节。
虽然目前Go实现了自举,但是编译Go编译器的编译器还是用C语言写的C语言字符串(字节数组)是非安全类型,使用尾零来标识字符串结束。
其中,尾零也占用一个字节。
尾零是 ASCII 第一个元素 0, 即:NUL(gdb) p version$1 = "v0.0.1"(gdb) p dateTime$2 = "2021-08-13,23:26:44"(gdb) p gitTag$3 = "v0.0.1"
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)