当前位置:首页 > 生活百科

go语言编译工具(go编译可执行文件)

栏目:生活百科日期:2025-04-02浏览:0

场景

公司线上运行的Go服务存在多个版本

时间:某天凌晨

事情:线上Go服务突然间 crash

紧急处理:重启Go服务

故障排查:查询日志,找出可能出现的堆栈信息以及追溯源码

问题:线上同时存在多个版本,如何知道当前 crash 的程序属于哪个版本?

添加版本信息的两种方案

方案1,手动添加版本信息:

package mainimport ("flag""fmt")// 下面三个变量,每次发版都要修改var version = "v0.0.1" // 程序版本号var gitTag = "v0.0.1" // git tag 号var dateTime = "2021-08-14 10:00:00" // 编译生成时间func 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")}

由于手动在代码中添加版本信息,所以在排查时可以查看到对应信息。

?  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 client

build 通过 -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"

“go语言编译工具(go编译可执行文件)” 的相关文章

太阳镜哪个牌子好,盘点世界十大名牌太阳镜

01.派丽蒙/Parom派丽蒙,是一个轻时尚的眼镜品牌,创立时间是1992年,派丽蒙专业设计适合东方人的时尚眼镜,材质优良,做工也是很精美的,设计风格时尚潮流,...

专业优化网站有哪些,网站排名优化技巧

做一个适合优化的网站首先:网站优化第一步就是做一个适合优化的网站,第一步:选一个适合优化的域名,域名尽量选择产品名称缩写+公司名称,尽量不要选择不相关的域名,域...

如何做团购推广,教你三个盈利的小技巧

相信现在的大多数年轻人的手机当中必备的软件就有一些团购软件,像是美团、大众点评、百度糯米等等。不论是吃的,还是一些娱乐节目,在这些团购网当中都可以轻松找到,并且...

asc文件怎么生成(后缀asc文件打开方式)

在PADS中,要对比并更新两个PCB或者ASC文件,操作步骤如下:1、点击工具栏的TOOLS,在下拉菜单中选择Compare/ECO&…,如下图2、...

中国互联网发展历程及现状(简介互联网近6年的发展情况)

随着互联网技术的不断革新和发展,互联网与传统产业跨界融合将更加广泛、深刻。一、产业互联网行业发展现状近年来,产业互联网发展步伐进一步加快,互联网技术对传统产业的...

12306 信息泄露怎么处理,揭秘其泄密背后的缘由

12月28日,一份铁路12306网站用户信息泄露的截图,在各大微信群流传开来,引发了网友的恐慌。中国铁路总公司随后在官方微博辟谣称,网传信息不实,铁路12306...

国外牛奶品牌排行榜(公认最受欢迎的5款进口牛奶)

常温牛奶又称UHT奶,它经过高温杀菌后在常温下能保存半年。——盖得日记普通消费者购买常温牛奶最应该关注的指标是营养价值,其次才是口感、性价比。国标《灭菌乳》中规...

企业微信号怎么申请流程(微信公众号开通步骤)

申请企业微信主体分为三类,我们在这里介绍关于企业这类主体(其他两类政府和组织基本相似)。企业微信怎么注册?请填写企业微信的全名和营业执照登记号码,并上传营业...

可以root的手机有哪些,推荐一款高配置手机

现在ROOT是手机的一大块事,可以说安卓手机无ROOT不安卓。在早前一般的安卓手机厂商都不会在官方系统上集成ROOT权限,后来慢慢的一些手机厂商就开始对ROOT...

2023年将全国推广驾照电子化(已经在多处试点)

中新网5月10日电公安部5月10日召开新闻发布会,会上介绍,公安部将推出试点推行驾驶证电子化等12项交管改革新措施。公安部交通管理局副局长刘宇鹏透露,公安部决定...