前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >"go build -X" 的妙用

"go build -X" 的妙用

作者头像
梦醒人间
发布2021-03-17 10:12:43
1.8K0
发布2021-03-17 10:12:43
举报
文章被收录于专栏:码农桃花源码农桃花源

不知道大家还记不记得,上次发了一篇关于 panic 检测机器人的文章,原理非常简单,简单回顾一下:

  1. 业务服务在 recover 函数里通过 HTTP 请求的方式向机器人上报 panic 栈信息。
  2. 机器人解析出 panic 栈里的代码行号,调用 gitlab 接口拿到该行代码的提交人、提交日期等信息。

当然,后面我又给机器人增加了一些其他的功能,例如自动拉群,自动提醒相关人修复 panic 代码等……

上面说的这些其实都很好实现,主要就是和飞书 API 打交道,再加上一些逻辑串连一下流程。目前机器人上报了 1000+ 次 panic,工作状态良好。

但偶尔还是有一些小问题的存在,例如有人用开发分支(非 master)上到线上测试环境(只读环境)测试一把,这时机器人还是用 master(默认)分支请求 gitlab 接口拿 commit 信息,拿到的信息就有可能不准。

那有没有什么好的方法能拿到正在运行的进程的代码分支呢?如果能拿到,机器人用代码路径+代码行号+代码分支,就可以从 gitlab 拿到正确的 commit 信息。

答案是有,通过 go build -X 注入。

那具体怎么玩的呢,通过一个小例子来说明。

下面是 build.sh 的代码:

代码语言:javascript
复制
#!/bin/sh

COMMIT_ID=`git log |head -n 1| awk '{print $2;}'`
AUTHOR=`git log |head -n 3| grep Author| awk '{print $2;}'`
BRANCH_NAME=`git branch | awk '/\*/ { print $2; }'`
SERVICE_INFO="$COMMIT_ID,$AUTHOR,$BRANCH_NAME"
echo $SERVICE_INFO
go build -ldflags "-X codebase/build-x/compile_info.ServiceInfo=$SERVICE_INFO" -o output/bin/build

第 3、4、5 行分别用 git 命令拿到本次提交的 commit-id,author,分支名;第 6 行用 “,” 将三者组合成一个字符串;第 8 行用 go build 命令,设置 ldflags,将变量 $SERVICE_INFO 注入到包变量 codebase/build-x/compile_info.ServiceInfo,这样在 Go 代码中就可以直接用了。

再看看我的 compile_info 包的代码,非常简单,就定义了一个变量:

代码语言:javascript
复制
package compile_info

var ServiceInfo string

执行完 go build 命令后,compile_info.ServiceInfo 就会被赋上值,在 main 函数里打印一下:

代码语言:javascript
复制
package main

import (
 "fmt"
 "codebase/build-x/compile_info"
)

func init() {
 fmt.Println("init: ", compile_info.ServiceInfo)
}

func main() {
 fmt.Println(compile_info.ServiceInfo)
}

先执行:

代码语言:javascript
复制
sh build.sh

再执行:

代码语言:javascript
复制
~/go/src/codebase/build-x$ ./output/bin/build

得到运行结果:

代码语言:javascript
复制
init:  9699dcaae31e7e5eab55a1d75283a6d7158a64e8,raoquancheng,master
9699dcaae31e7e5eab55a1d75283a6d7158a64e8,raoquancheng,master

可知,在 init 函数里我们就可以拿到 compile_info.ServiceInfo 的值了。

代码文件结构如下:

文件结构

原理也没啥可探究的,就是通过 -ldflags 给链接器传参数:

-X definition: 添加形式为 importpath.name=value 的字符串值定义

其他的一些常见的命令用处:

-s 的作用是去掉符号信息。-w 的作用是去掉调试信息。go build -ldflags "-s -w" -o xxx

之前看到公司项目里 build 脚本里的一些命令不知道有啥用,真正到了用的时候才惊呼:原来是这样!

今天的 go build 妙用你学会了吗?也许下次就可以在同事面前装 B 了,当然如果碰到了老司机,也可能会被打脸。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农桃花源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档