在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

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

  1. visual studio添加对项目的多版本sln配置

    我们开发的库文件,适用于多个APP产品,而不同的产品使用了不同版本的IDE工具,VS2005,vs2008,vs2010以及vs2013等,所以为了跟app兼容,我们也需要提供不同版本的库文件,这时就 ...

  2. IntelliJ IDEA for Mac 如何在当前的普通Java项目中创建新的模块/添加模块/创建模块

    文章目录 添加模块的入口 创建新的项目模块 添加模块的入口 添加新的模块的入口有两个,如下图所示: 第一种方式,[File] --> [New] --> [Module]: 第二种方式,打 ...

  3. 【解决问题】Qt项目不能添加新文件Files are not automatically added to the CmakeLists.text file of the CMake project.

    Qt项目不能添加新文件Files are not automatically added to the CmakeLists.text file of the CMake project. 在Qt项目 ...

  4. 物联网新零售项目 物联网亿万级通信一站式解决方案EMQ

    物联网亿万级通信一站式解决方案EMQ 1. MQTT 1.1 MQTT简介 1.1.1 什么是MQTT ​ MQTT(Message Queuing Telemetry Transport,消息队列遥 ...

  5. 使用gitlab创建项目和添加成员,并提交本地代码至gitlab远程仓库

    一.背景 GitHub和GitLab 都是基于web的Git仓库,使用起来二者差不多,它们都提供了分享开源项目的平台,为开发团队提供了存储.分享.发布和合作开发项目的中心化云存储的场所. GitHub ...

  6. 新个人项目-- 拼图游戏

    正式开博记录,想和很久但一直没有执行的新个人项目-- 拼图游戏. 完全由前端技术完成.从简单粗糙到复杂精细. 为了督促自己持续推进该项目,立博为证. 之后会陆续将文档.计划补充上来.都是非官方非正式的 ...

  7. Entity Framework 的小实例:在项目中添加一个实体类,并做插入操作

    Entity Framework 的小实例:在项目中添加一个实体类,并做插入操作 Entity Framework 的小实例:在项目中添加一个实体类,并做插入操作 1>. 创建一个控制台程序 2 ...

  8. 使用 dotnet-outdated 维护项目 nuget 包版本

    使用 dotnet-outdated 维护项目 nuget 包版本 Intro 我们项目中或多或少都会有一些 NuGet 包,使用到 NuGet 包时,如何保证我们的 NuGet 包不会太旧呢?我们可 ...

  9. Abp Vnext应用程序项目中添加docker支持的小结

    文章目录 介绍 具体步骤 1.创建项目 2.添加docker支持 3.调整 4.运行实例 总结 介绍 abp vnext 里面的只有 module 项目里面是自动添加 docker 支持的,因为其是面 ...

  10. Linux下SVN创建新的项目

    Linux下SVN创建新的项目 Linux环境下的SVN创建新的项目 一.前置条件: 1)有安装了linux系统的服务器,123.*.*.29 2)服务器上安装了svn,本人服务器的svn的数据安装的 ...

最新文章

  1. 重庆南岸召开总结会,今年将引进30家车联网企业
  2. 怎么判断日出时间早晚_珠海最全防堵攻略,知道这些上班时间或缩短半小时!有大数据分析!...
  3. coreData使用
  4. 临床观察性研究论文如何撰写“方法”?
  5. VTK:InfoVis之DelimitedTextWriter
  6. 线程池状态和使用注意点
  7. TableView下拉图片放大
  8. [FY20 创新人才班 ASE] 第 1 次作业成绩
  9. 量子力学到底神奇在哪里?看完这个,我的认知彻底坍塌了
  10. android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一
  11. javascript进制转换_《算法笔记》3.5小节——入门模拟-gt;进制转换
  12. js——window.open用法
  13. python爬虫工程师必学app数据抓取实战_另辟蹊径,appium抓取app应用数据了解一下!...
  14. 金蝶kiss专业版财务软件下载。
  15. vos网络电话系统怎样搭建?
  16. Unity 3D官方教程——2D Roguelike学习记录
  17. 艰难环境下,面腾讯、美团、商汤科技等七家大厂前端有感
  18. 计算机导论论文对课程的思考,计算机导论课浅析论文
  19. 使用yum安装java
  20. LABVIEW绘制等高线

热门文章

  1. vue 前端导出Excel表格(基础版 + 多级标题)纯前端导出
  2. MTK芯片型号和对应支持功能
  3. 为什么获取crm服务器信息失败,CRM项目失败的七大原因
  4. linux | setfacl - - 细分文件权限
  5. Setfacl : Operation not supported
  6. ES6 Array every()实例讲解
  7. 上计算机专业的梦想与目标,坚定升学目标,放飞大学梦想 ——计算机专业部召开强化班战前动员会...
  8. linux获取DNS地址 C语言,使用C语言获取DNS nameserver并进行域名解析
  9. 实战:从文件夹中庞大的excel(.xlsx)文件中提取并整合数据
  10. python-opencv之人脸检测