Go语言程序编译注入版本信息,提升Debug速度!

本文介绍如何使用gobuild-ldflags命令注入版本信息,并通过Makefile简化编译流程,实现Go服务版本的有效追踪。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

为了对运行程序进行版本追踪,避免各个版本的服务程序混淆,通常的做法为在go build编译的时候程序注入
版本标志、编译时间、当前分支、当前 Tag、当前的提交号等信息,让go程序在运行的时候就可以打印编译时候的参数情况。

go build -ldflags命令

ldflags简介

golang项目常用三个参数,含义如下:

  -X definition #注入变量定义
    	add string value definition of the form importpath.name=value
  -s	disable symbol table # 禁用符号表
  -w	disable DWARF generation # 禁用调试信息

-s -w俩个参数可以减小构建二进制包大小。

go build 命令

  CGO_ENABLED=0 go build \
     -ldflags " \
     -X 'main.BuildVersion=${build_version}' \
     -X 'main.BuildGoVersion=${go_version}' \
     -X 'main.BuildTime=${build_time}' \
     -X 'main.BuildCommit=${build_commit}' \
     -o ${APP_NAME}
     " main.go

CGO_ENABLED=0 禁用cgo。

-X ‘main.BuildVersion=${build_version}’ 编译时候会想main中注册变量BuildVersion,如下代码中main.go代码即可接受。

代码

package main

import (
	"flag"
	"fmt"
)

// 构建版本信息
var (
	BuildVersion   = ""
	BuildGoVersion = ""
	BuildCommit    = ""
	BuildTime      = ""
)

func main() {

	// 构建信息,golang版本 commit id 时间
	var version bool
	flag.BoolVar(&version, "v", false, "version")
	flag.Parse()
	if version {
		fmt.Printf("go version: %s\n,Build version: %s\n, Build commit: %s\n, Build time: %s\n",
			BuildGoVersion, BuildVersion, BuildCommit, BuildTime)
		return
	}
	// 业务逻辑

}

编译后结果运行如下

$ ./demo_app -v         
go version: go version go1.19.2 darwin/amd64,
Build version: dev_8899bca, 
Build commit: 8899bca, 
Build time: 2022-11-21T15:12:57Z

Makefile

简介

Makefile简单理解为它定义了一个项目文件的编译规则。早期适用于 C/C++ 工程的编译,一旦写编写好 Makefile 文件,
只需要一个 make 命令,整个工程就开始自动编译,不再需要手动执行 GCC 命令。
后面随着逐渐发展其它项目也开始使用Makefile进行服务的编译,极大简化项目编译过程。

所以我们将上文的go build命令集合进Makefile文件中,简化编译过程。

Makefile结构说明

Makefile里主要包含了五个东西:变量定义、显式规则、隐晦规则、文件指示和注释。

  1. 变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
  2. 显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。 刚才写的疑似shell脚本的Makefile全部都是显示规则。
  3. 隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
  4. 文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样。
  5. 注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符。

实践

获取仓库taggit describe --tags --abbrev=0

获取仓库最近提交commit id
git rev-parse --short HEAD

获取仓库当前所处分支git rev-parse --abbrev-ref HEAD

在go项目仓库根目录下 创建Makefile文件

git_rev    = $(shell git rev-parse --short HEAD)
git_tag    = $(shell git describe --tags --abbrev=0)
git_branch = $(shell git rev-parse --abbrev-ref HEAD)
app_name   = "demo_app"

BuildVersion := $(git_branch)_$(git_rev)
BuildTime := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
BuildCommit := $(shell git rev-parse --short HEAD)
BuildGoVersion := $(shell go version)

# in detached HEAD state
ifeq ($(git_branch), HEAD)
	git_branch = $(shell git show-ref | grep $(shell git show HEAD | sed -n 1p | cut -d " " -f 2) | sed 's|.*/\(.*\)|\1|' | grep -v HEAD | sort | uniq | head -n 1)
	# when git checkout <<tag>>, branch may still be empty
	ifeq ($(git_branch), )
		git_branch := $(git_tag)
	endif
	BuildVersion := $(git_branch)_$(git_rev)
endif

ifeq ($(git_branch), develop)
	BuildVersion := develop_$(git_rev)
endif

ifeq ($(git_branch), master)
	BuildVersion := release_$(git_tag)_$(git_rev)
endif

# -ldflag 参数
GOLDFLAGS = -s -w -X 'main.BuildVersion=$(BuildVersion)'
GOLDFLAGS += -X 'main.BuildTime=$(BuildTime)'
GOLDFLAGS += -X 'main.BuildCommit=$(BuildCommit)'
GOLDFLAGS += -X 'main.BuildGoVersion=$(BuildGoVersion)'

# go mod
mod:
	go mod tidy

all: linux

# linux 构建二进制
linux:
	@GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o "$(app_name)" -ldflags "$(GOLDFLAGS)"
	
# arm 构建二进制
arm:
	@GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o "$(app_name)" -ldflags "$(GOLDFLAGS)"
	
# mac 构建二进制
mac:
	@GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -o "$(app_name)" -ldflags "$(GOLDFLAGS)"

make linux 即可生成demo_app二进制服务

编译后结果运行如下,与go build之后结果一样

$ ./demo_app -v         
go version: go version go1.19.2 darwin/amd64,
Build version: dev_8899bca, 
Build commit: 8899bca, 
Build time: 2022-11-21T15:12:57Z

小结

通过makefile与-ldflags结合注入服务版本信息,是一种常见方式,可以帮助我们快速定位一些基础问题,避免踩坑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

merlin.feng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值