1

Go channel 的妙用

 2 years ago
source link: https://qcrao.com/2021/02/04/ingenious-use-of-channel/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go channel 的妙用

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

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

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

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

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

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

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

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

下面是 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 行用 “,” 将三者组合成一个字符串;第 8 行用 go build 命令,设置 ldflags,将变量 $SERVICE_INFO 注入到包变量 codebase/build-x/compile_info.ServiceInfo,这样在 Go 代码中就可以直接用了。

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

package compile_info

var ServiceInfo string

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

package main

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

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

func main() {
fmt.Println(compile_info.ServiceInfo)
}
sh build.sh
~/go/src/codebase/build-x$ ./output/bin/build

得到运行结果:

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 了,当然如果碰到了老司机,也可能会被打脸。

【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/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK