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

article/2025/10/6 7:47:20

在这里插入图片描述

在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.gogo 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.go1. 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.Argsif 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/bashecho "(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, strippedecho "(2)Linux 下编译 Mac 和 Windows 平台64位可执行程序:"
#CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
#CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go buildecho "(3)Mac 下编译 Linux 和 Windows平台 64位 可执行程序:"
#CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
#CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go buildecho "动态传值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 strippedecho "手动传值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


http://chatgpt.dhexx.cn/article/4LbysYbU.shtml

相关文章

linux编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解

参考到下面博客,把编译步骤分解的很细 linuxC编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解 - yongfengnice - 博客园 CPPFLAGS : 预处理器需要的选项 如:-I (大写i指定头文件路径) CFLAGS:编译的时候使用的参数 –Wall –g -c LDFLAGS &…

【Java位运算】异或运算的使用

异或运算有个特性:两个相同的数做异或运算,结果为0。 n ^ n 0;常用的方式是查找数组中只出现一次的数字。 例如:在一个数组中,只有一个数字出现了一次,其余数字都出现了两次。 求这个数字。利用异或运算的特性进行计…

java中与运算,或运算,异或运算

Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^) 位运算符主要针对二进制,它包括了:“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻…

Java中的与、或、非以及异或( | ~ ^)运算符的运算原理

首先,我们要知道Java存储数据是保存的补码,如果对原码、反码以及补码不太懂,可以参考我的另一篇博客。 1. Java的 与( & ) 运算 所有的逻辑运算都是按位计算的,所以第一步就是先把数据转成二进制,然后相应位进行…

java运算符 与()、非(~)、或(|)、异或(^)

欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 位运算符主要针对二进制,它包括了:“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻辑运算符&…

java中的异或非运算

一、java 与或非 操作 与(&)、非(~)、或(|)、异或(^) 1.与运算符 与运算符用符号“&”表示,其使用规律如下: 两个操作数中位都为1&#x…

java运算符异或(^)的用法

Java中的位运算符中有一个叫做异或的运算符,符号为(^),其主要是对两个操作数进行位的异或运算,相同取0,相反取1。即两操作数相同时,互相抵消。 试例:13 与15 两个整数的异或 public static void…

一文搞懂 位运算 异或(Java实现)

提起异或想必很多小伙伴们既熟悉又陌生,熟悉是因为好像在离散数学或者学某个编程语言 时听过这个东西,而陌生呢,则是因为自己平时并没有用过,以至于当在某个场景 (我猜是在看 题解或者某篇博客时) 看到这…

java中异或运算的应用

java中异或运算(^)的应用 异或运算法则 1. a ^ b b ^ a   2. a ^ b ^ c a ^ (b ^ c) (a ^ b) ^ c;   3. d a ^ b ^ c 可以推出 a d ^ b ^ c.   4. a ^ b ^ a b. 异或运算 1、异或是一个数学运算符。应用于逻辑运算。   2、例如:真异或假的结果是…

java的异或运算

一、题目 输入两个数,交换后输出 二、解题思路 一开始学习的语言是c语言,里面非常有特色的是指针,通过传引用可以直接交换两个数。但java无法达成这种操作,翻阅资料找到了一种有趣的解法:异或! 异或原理: …

java基础-异或运算

小伙伴们,你们好呀!我是老寇! 异或运算主要用于判断两个值是否一样 异或运算的3个性质: 1.任何数和0进行异或运算,结果是原来的数,即b⊕0b 2.任何数和其自身进行异或运算,结果为0,即…

Java中的异或运算符^

Testpublic void test2() {int a2;int b3;aa^b;ba^b;aa^b;System.out.println("a"a",b"b);}第一种:用真实值计算 ^是异或运算符,异或的规则是转换成二进制比较,相同为0,不同为1. 一个数a与另一个数b异或的结果…

java中的异或运算

👏作者简介:大家好,我是Rockey,不知名企业的不知名Java开发工程师 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦 📝联系方式:he18339193956&…

HTTP Status 505 – HTTP Version Not Supported

这个大部分的原因不是httpserver不支持,而是请求url里有空格,检查有空格UTF-8编码再传 比如:远程调用服务端地址有空格 去除空格

HTTP Status 500 解决办法

HTTP Status 500 解决办法 在Java web 论坛系统中也遇见了这个问题,在这里就提供一个解决的办法。 图中显示 int idInteger.parseInt(request.getParameter("id")); 这一段有错误。这里是因为id的值不能为null,不然就会出现这个错误 修改如…

Tomcat HTTP Status 404 tomcat 404问题解决

今天初次使用tomcat的时候,用浏览器访问总是不成功。经过一番周折总算成功了,虽然这个知识点不是很难,但还是写篇博客,希望能帮助那些初学者。(注:笔者用的是:tomcat 7) 前提:你的tomcat可以访…

svn提交报错Unexpected HTTP status 413 'Request Entity Too Large' on

问题原因:nginx的client_max_body_size设置过小,默认 1M,如果请求的正文数据大于client_max_body_size,HTTP协议会报错 413 Request Entity Too Large。 解决方案:把这个值调大就可以了。

HTTP Status 404 - 解决办法

HTTP Status 404 - 解决办法 今天,我在从仓库导入web项目的时候出现了一个问题: 首先,我想的是为什么会出现,这样的问题,然后我对这个问题进行了描述,准备在网上找找解决方法,大多数给出的答案…

HTTP Status 500 – Internal Server Error

第一次碰到500错误,标题很明显,内部服务器错误,解决此类问题重点在于会看错误提示信息,之前一直没有这个意识,看到报错直接百度,其实我们稍微注意一下信息提示就能解决大部分问题,上图: 看下第二条Message,标注了/iframe/head.jsp页面,后边括号表明为第一行第二列(个…

HTTP Status 400的排错步骤 与HTTP Status 404的排错步骤

一、前言:一个问题有暗含两个错误:400和404 二、HTTP Status 400 这是在跳转修改的界面出现,跳不过去说明路径相关有问题 上面 400的解决了,然后运行404又出来了 三、HTTP Status 404 看到资源问题,就去看下导包没有&a…