"go build -X" 的妙用
不知道大家還記不記得,上次發(fā)了一篇關(guān)于 panic 檢測(cè)機(jī)器人的文章,原理非常簡(jiǎn)單,簡(jiǎn)單回顧一下:
- 業(yè)務(wù)服務(wù)在 recover 函數(shù)里通過(guò) HTTP 請(qǐng)求的方式向機(jī)器人上報(bào) panic 棧信息。
- 機(jī)器人解析出 panic 棧里的代碼行號(hào),調(diào)用 gitlab 接口拿到該行代碼的提交人、提交日期等信息。
當(dāng)然,后面我又給機(jī)器人增加了一些其他的功能,例如自動(dòng)拉群,自動(dòng)提醒相關(guān)人修復(fù) panic 代碼等……
上面說(shuō)的這些其實(shí)都很好實(shí)現(xiàn),主要就是和飛書 API 打交道,再加上一些邏輯串連一下流程。目前機(jī)器人上報(bào)了 1000+ 次 panic,工作狀態(tài)良好。
但偶爾還是有一些小問(wèn)題的存在,例如有人用開發(fā)分支(非 master)上到線上測(cè)試環(huán)境(只讀環(huán)境)測(cè)試一把,這時(shí)機(jī)器人還是用 master(默認(rèn))分支請(qǐng)求 gitlab 接口拿 commit 信息,拿到的信息就有可能不準(zhǔn)。
那有沒有什么好的方法能拿到正在運(yùn)行的進(jìn)程的代碼分支呢?如果能拿到,機(jī)器人用代碼路徑+代碼行號(hào)+代碼分支,就可以從 gitlab 拿到正確的 commit 信息。
答案是有,通過(guò) go build -X 注入。
那具體怎么玩的呢,通過(guò)一個(gè)小例子來(lái)說(shuō)明。
下面是 build.sh 的代碼:
#!/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 行用 “,” 將三者組合成一個(gè)字符串;第 8 行用 go build 命令,設(shè)置 ldflags,將變量 $SERVICE_INFO 注入到包變量 codebase/build-x/compile_info.ServiceInfo,這樣在 Go 代碼中就可以直接用了。
再看看我的 compile_info 包的代碼,非常簡(jiǎn)單,就定義了一個(gè)變量:
package compile_info
var ServiceInfo string
執(zhí)行完 go build 命令后,compile_info.ServiceInfo 就會(huì)被賦上值,在 main 函數(shù)里打印一下:
package main
import (
"fmt"
"codebase/build-x/compile_info"
)
func init() {
fmt.Println("init: ", compile_info.ServiceInfo)
}
func main() {
fmt.Println(compile_info.ServiceInfo)
}
先執(zhí)行:
sh build.sh
再執(zhí)行:
~/go/src/codebase/build-x$ ./output/bin/build
得到運(yùn)行結(jié)果:
init: 9699dcaae31e7e5eab55a1d75283a6d7158a64e8,raoquancheng,master
9699dcaae31e7e5eab55a1d75283a6d7158a64e8,raoquancheng,master
可知,在 init 函數(shù)里我們就可以拿到 compile_info.ServiceInfo 的值了。
代碼文件結(jié)構(gòu)如下:
文件結(jié)構(gòu)
原理也沒啥可探究的,就是通過(guò) -ldflags 給鏈接器傳參數(shù):
-X definition: 添加形式為 importpath.name=value 的字符串值定義
其他的一些常見的命令用處:
-s的作用是去掉符號(hào)信息。-w的作用是去掉調(diào)試信息。go build -ldflags "-s -w" -o xxx
之前看到公司項(xiàng)目里 build 腳本里的一些命令不知道有啥用,真正到了用的時(shí)候才驚呼:原來(lái)是這樣!
今天的 go build 妙用你學(xué)會(huì)了嗎?也許下次就可以在同事面前裝 B 了,當(dāng)然如果碰到了老司機(jī),也可能會(huì)被打臉。
資料分享,關(guān)注公眾號(hào)回復(fù)指令:
- 回復(fù)【加群】,和大佬們一起成長(zhǎng)。
- 回復(fù)【000】,下載一線大廠簡(jiǎn)歷模板。
- 回復(fù)【001】, 送你 Go 開源電子書。
