Go 命令 『go build -X』 的妙用
不知道大家还记不记得,上次发了一篇关于 panic 检测机器人的文章,原理非常简单,简单回顾一下:
- 业务服务在 recover 函数里通过 HTTP 请求的方式向机器人上报 panic 栈信息。
- 机器人解析出 panic 栈里的代码行号,调用 gitlab 接口拿到该行代码的提交人、提交日期等信息。
当然,后面我又给机器人增加了一些其他的功能,例如自动拉群,自动提醒相关人修复 panic 代码等……
上面说的这些其实都很好实现,主要就是和飞书 API 打交道,再加上一些逻辑串连一下流程。目前机器人上报了 1000+ 次 panic,工作状态良好。
但偶尔还是有一些小问题的存在,例如有人用开发分支(非 master)上到线上测试环境(只读环境)测试一把,这时机器人还是用 master(默认)分支请求 gitlab 接口拿 commit 信息,拿到的信息就有可能不准。
那有没有什么好的方法能拿到正在运行的进程的代码分支呢?如果能拿到,机器人用代码路径+代码行号+代码分支,就可以从 gitlab 拿到正确的 commit 信息。
答案是有,通过 go build -X
注入。
那具体怎么玩的呢,通过一个小例子来说明。
下面是 build.sh
的代码:
1#!/bin/sh
2
3COMMIT_ID=`git log |head -n 1| awk '{print $2;}'`
4AUTHOR=`git log |head -n 3| grep Author| awk '{print $2;}'`
5BRANCH_NAME=`git branch | awk '/\*/ { print $2; }'`
6SERVICE_INFO="$COMMIT_ID,$AUTHOR,$BRANCH_NAME"
7echo $SERVICE_INFO
8go 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 包的代码,非常简单,就定义了一个变量:
执行完 go build
命令后,compile_info.ServiceInfo 就会被赋上值,在 main 函数里打印一下:
1package main
2
3import (
4 "fmt"
5 "codebase/build-x/compile_info"
6)
7
8func init() {
9 fmt.Println("init: ", compile_info.ServiceInfo)
10}
11
12func main() {
13 fmt.Println(compile_info.ServiceInfo)
14}
先执行:
1sh build.sh
再执行:
1~/go/src/codebase/build-x$ ./output/bin/build
得到运行结果:
1init: 9699dcaae31e7e5eab55a1d75283a6d7158a64e8,raoquancheng,master
29699dcaae31e7e5eab55a1d75283a6d7158a64e8,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 了,当然如果碰到了老司机,也可能会被打脸。
参考资料
【ldflags go version】 https://ms2008.github.io/2018/10/08/golang-build-version/
【go build 命令】 https://github.com/hyper0x/go_command_tutorial/blob/master/0.1.md
【Go 编译命令】 https://chenwenke.cn/blog/2019/11/05/2019-11-05-go-build/
- 原文作者:饶全成
- 原文链接:https://qcrao.com/post/ingenious-use-of-go-build-x/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。