Go新项目-项目添加版本说明,以及参数传递:ldflags、gcflags,外加stripped说明(5)

在这里插入图片描述

在Go项目中,会存在展示该项目的版本信息,以及打包日期,项目版本,Go版本等;继Go新项目-编译项目的细节(4)以后再记录下编译优化方向,刚好也有项目版本输出的需求。

关键词:ldflags、gcflag、stripped

ldflags

**************** ldflags ****************

  • 当把应用程序部署到生产环境中时,用版本信息和其他元数据构建二进制文件将改善你的监控、日志和调试过程,增加识别信息以帮助跟踪你的构建时间.
    go 的 ldflags参数
  • -w 去掉调试信息
  • -s 去掉符号表
  • -X 注入变量, 编译时赋值

-w 和 -s 通常一起使用,用来减少可执行文件的体积。但删除了调试信息后,可执行文件将无法使用 gdb/dlv 调试

使用范围可以在go install 、go build、go run 、go test中使用

Module=github.com/pubgo/xxx
GOPATH=$(shell go env GOPATH)
Version=$(shell git tag --sort=committerdate | tail -n 1)
GoVersion=$(shell go version)
BuildTime=$(shell date "+%F %T")
CommitID=$(shell git rev-parse HEAD)
LDFLAGS:=-ldflags "-X 'github.com/pubgo/xxx/version.GoVersion=${GoVersion}' \
-X 'github.com/pubgo/xxx/version.BuildTime=${BuildTime}' \
-X 'github.com/pubgo/xxx/version.GoPath=${GOPATH}' \
-X 'github.com/pubgo/xxx/version.CommitID=${CommitID}' \
-X 'github.com/pubgo/xxx/version.Module=${Module}' \
-X 'github.com/pubgo/xxx/version.Version=${Version:-v0.0.1}'"

编译

go build ${LDFLAGS} -mod vendor -race -v -o main main.go
go build -ldflags "-w -s" -mod vendor -race -v -o main main.go

go build -ldflags "-w -s"  -race -v -o main main.go

gcflags

**************** gcflags ****************

  • -N参数代表禁止优化,
  • -l参数代表禁止内联,
  • -c int: 编译过程中的并发数,默认是1

go在编译目标程序的时候会嵌入运行时(runtime)的二进制,
禁止优化和内联可以让运行时(runtime)中的函数变得更容易调试.

go build -gcflags='all=-N -l' main.go
1. go tool compile -N -l -S main.go
2. go tool compile -N -l main.go
    1. go tool objdump main.o 		//反汇编出代码
    2. go tool objdump -s Do main.o //反汇编特定的函
3. go build -gcflags -S main.go
4. go tool compile 和 go build -gcflags -S 生成的是过程中的汇编,和最终的机器码的汇编可以通过go tool objdump生成

逃逸分析

该参数不光优化编译的二进制包,还能进行项目的逃逸分析

go build -gcflags="-m -l" ./main.go
  • 这一命令中,-m 表示打印出逃逸分析信息,-l 表示禁止内联,可以更好地观察逃逸。
  • 从以下输出结果可以看到,发生了逃逸,也就是说指针作为函数返回值的时候,一定会发生逃逸。
// 变量 m 没有逃逸,反而被变量 m 引用的变量 s 逃逸到了堆上。
// 所以被map、slice 和 chan 这三种类型引用的指针一定会发生逃逸的。

func main() {
	m := map[int]*string{}
	s := "小胡"
	m[0] = &s
}

stripped

文件属性解释词:stripped,曾经在编译Go项目过程中,没有转为Linux适配的二进制,而导致出错(cannot execute binary file),就是采用 file 文件名 命令来分析二进制文件的属性;来快速定位问题。

**************** stripped ****************

  • 同样名字的动态库,带not stripped库会大很多。
    • stripped 表示执行程序中剔除了符号表信息
    • not stripped 表示没有剔除
  • 一般最终的程序都会使用strip来减小可执行文件的体积,而调试中的程序则不使用strip。
  • strip 是一个命令,就是负责剔除符号表信息,这样执行程序的尺寸会变小,但是不便调试

主程序

  • 用于项目编译过程展示:项目版本号、日期、git版本、go版本;
var (
	version    = "" // "1.0.0"
	buildstamp = "" // time.Now()
	githash    = "" // "1.0.0"
	goversion  = "" // fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH)
	
	// VERSION    string
	// BUILD_TIME string
	// GO_VERSION string
)

func main() {
	// fmt.Printf("%s\n%s\n%s\n", VERSION, BUILD_TIME, GO_VERSION)
	args := os.Args
	if len(args) == 2 && (args[1] == "--version" || args[1] == "-v") {
		fmt.Printf("Version : %s\n", version)
		fmt.Printf("Git Commit Hash: %s\n", githash)
		fmt.Printf("CST Build Time : %s\n", buildstamp)
		fmt.Printf("Golang Version : %s\n", goversion)
		return
	}
}

build.sh

展示一个编译的shell脚本,补充上篇在写项目编译的过程只是给出了命令,没有通过脚本执行,这样提升了了编译的效率

#!/bin/bash

echo "(1)Windows下 编译 Linux流程:"
CGO_ENABLED=0 GOOS=linux GOARCH=amd64  go  build -ldflags="-s -w" main.go

# 文件 file main的属性
# main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

echo "(2)Linux 下编译 Mac 和 Windows 平台64位可执行程序:"
#CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
#CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

echo "(3)Mac 下编译 Linux 和 Windows平台 64位 可执行程序:"
#CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
#CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build



echo "动态传值1-完整版(注入-版本号、时间date、版本git、go版本): -u 是展示UTC时间"
#flags="-X main.version=1.0.0 -X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git describe --long --dirty --abbrev=14` -X 'main.goversion=$(go version)'"
flags="-X main.version=1.0.0 -X main.buildstamp=`date '+%Y-%m-%d_%H:%M:%S'` -X main.githash=`git describe --long --dirty --abbrev=14` -X 'main.goversion=$(go version)'"
CGO_ENABLED=1 GOOS=linux GOARCH=amd64  go build -ldflags "$flags" -x -o build-version main.go

# 文件 file bulid-version的属性
# build-version: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped


echo "手动传值2 (注入:版本号、时间、go版本) :"
# data = UTC
#CGO_ENABLED=1 GOOS=linux GOARCH=amd64  go build -ldflags "-X main.VERSION=1.0.0 -X 'main.BUILD_TIME=`date -u '+%Y-%m-%d_%I:%M:%S%p'`' -X 'main.GO_VERSION=$(go version)'"

# data = CST
CGO_ENABLED=0 GOOS=linux GOARCH=amd64  go build -ldflags "-X main.VERSION=1.0.0 -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=$(go version)'"

参考:https://www.digitalocean.com/community/tutorials/using-ldflags-to-set-version-information-for-go-applications

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值