在实际开发中,当开发完一个 apiserver 特性后,会编译 apiserver 二进制文件并发布到生产环境,很多时候为了定位问题和出于安全目的(不能发错版本),我们需要知道当前 apiserver 的版本,以及一些编译时候的信息,如编译时 Go 的版本、Git 目录是否 clean,以及基于哪个 git commmit 来编译的。在一个编译好的可执行程序中,我们通常可以用类似 ./app_name -v 的方式来获取版本信息。

我们可以将这些信息写在配置文件中,程序运行时从配置文件中取得这些信息进行显示。但是在部署程序时,除了二进制文件还需要额外的配置文件,不是很方便。或者将这些信息写入代码中,这样不需要额外的配置,但要在每次编译时修改代码文件,也比较麻烦。Go 官方提供了一种更好的方式:通过 -ldflags -X importpath.name=value(详见 -ldflags -X importpath.name=value)来给程序自动添加版本信息。

1.增加参数-v

package main

import (
"encoding/json"
"fmt"
"os"
...
v "apiserver/pkg/version"
...
) var (
version = pflag.BoolP("version", "v", false, "show version info.")
) func main() {
pflag.Parse()
if *version {
v := v.Get()
marshalled, err := json.MarshalIndent(&v, "", " ")
if err != nil {
fmt.Printf("%v\n", err)
os.Exit(1)
} fmt.Println(string(marshalled))
return
}
...
}

pkg/version包中的实现:

base.go

package version

// 变量通过-ldflags -X importpath.name=value在编译时传入程序中
var (
gitTag = "" //
gitBranch = ""
gitCommit = "$Format:%H$"
gitTreeState = "not a git tree"
buildDate = "1970-01-01T00:00:00Z"
)

version.go

package version

import (
"fmt"
"runtime"
) type Info struct {
GitTag string `json:"gitTag"`
GitBranch string `json:"gitBranch"`
GitCommit string `json:"gitCommit"`
GitTreeState string `json:"gitTreeState"`
BuildDate string `json:"buildDate"`
GoVersion string `json:"goVersion"`
Compiler string `json:"compiler"`
Platform string `json:"platform"`
} func (info Info) String() string {
return info.GitTag
} func Get() Info {
return Info{
GitTag: gitTag,
GitBranch: gitBranch,
GitCommit: gitCommit,
GitTreeState: gitTreeState,
BuildDate: buildDate,
GoVersion: runtime.Version(),
Compiler: runtime.Compiler,
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
}
}

其中的gitTag, gitBranch,gitComit,gitTreeState,buildDate信息都是在build的时候, 使用-ldflags -X key=value的方式指定参数

Makefile文件中:

.PHONY: all build windows mac run tidy check cert test cover lint docker clean help

BIN_FILE=golang-demo
MAIN_FILE=./cmd/app/main.go SHELL := /bin/bash
BASEDIR = $(shell pwd) # build with verison infos
versionDir = "golang-demo/pkg/version"
## 获取仓库tag
gitTag = $(shell if [ "`git describe --tags --abbrev=0 2>/dev/null`" != "" ];then git describe --tags --abbrev=0; else git log --pretty=format:'%h' -n 1; fi)
buildDate = $(shell TZ=Asia/Shanghai date +%FT%T%z)
gitCommit = $(shell git log --pretty=format:'%H' -n 1)
gitTreeState = $(shell if git status|grep -q 'clean';then echo clean; else echo dirty; fi)
gitBranch = $(shell git rev-parse --abbrev-ref HEAD) ldflags="-w -X ${versionDir}.gitTag=${gitTag} -X ${versionDir}.buildDate=${buildDate} -X ${versionDir}.gitBranch=${gitBranch} -X ${versionDir}.gitCommit=${gitCommit} -X ${versionDir}.gitTreeState=${gitTreeState}" # 默认执行
all: build # 打包成二进制文件
build: tidy check
@CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags $(ldflags) -o $(BIN_FILE)_linux $(MAIN_FILE) windows: tidy check
@CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -v -ldflags "-w -s" -o $(BIN_FILE)_windows.exe $(MAIN_FILE) mac: tidy check
@CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -ldflags "-w -s" -o $(BIN_FILE)_darwin $(MAIN_FILE) # 启动服务
run:
@go run $(MAIN_FILE) -c ./config/config.yaml tidy:
@go mod tidy # 代码验证
check:
@gofmt -s -w ./
@go vet $(MAIN_FILE) cert:
@openssl req -new -nodes -x509 -out config/server.crt -keyout config/server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=127.0.0.1/emailAddress=xxxxx@qq.com" # 单元测试
test:
@go test ./... # 覆盖测试
cover:
@go test -coverprofile xx.out
@go tool cover -html=xx.out lint:
@golangci-lint run --enable-all docker:
@docker build -t golang-demo:latest . clean:
@go clean -x
rm -f "xx.out" help:
@echo "make - 格式化go代码 并编译生成二进制文件"
@echo "make test - 执行测试case"
@echo "make check - 代码检查"
@echo "make cover - 检测测试覆盖率"
@echo "make run - 启动服务"
@echo "make lint - 执行代码检查"
@echo "make docker - 生成Docker镜像"
@echo "make clean - 清理中间目标文件"
@echo "make build - 编译成二进制文件(默认:Linux)"
@echo "make windows - 编译成二进制文件(Windows)"
@echo "make mac - 编译成二进制文件(Mac)" # include ./TestMakefile 包含其他Makefile

-w:  去除调试信息, 无法使用gdb调试, 但是二进制文件更小

执行./golang-demo -v

{
"gitTag": "d62a870",
"gitBranch": "master",
"gitCommit": "d62a87056066b2f8ecf6caf64b3bd1d80d60a5e1",
"gitTreeState": "dirty",
"buildDate": "2023-08-24T17:10:45+0800",
"goVersion": "go1.20.7",
"compiler": "gc",
"platform": "linux/amd64"
}

golang之增加版本信息功能的更多相关文章

  1. webpack 打包增加版本信息

    What do we need? 笔者目的是在vue项目打包后的 dist/index.html 文件中写入本次打包git用户.最后一次git提交信息,这样做的目的是便于线上项目的管理和防止同事之间的 ...

  2. GetFileVersionInfoSize函数确定操作系统是否可以检索指定文件的版本信息

    GetFileVersionInfoSize函数 -------------------------------------------------- ------------------------ ...

  3. java在线聊天项目0.3版本 制作客户端窗体,实现发送按钮和回车发送信息功能,使用ActionListener监听事件中actionPerformed方法(用内部类和匿名内部类两种方法)

    方法一,使用匿名内部类的监听方法,因方法一致代码稍冗余 package com.swift; import java.awt.BorderLayout; import java.awt.Color; ...

  4. mysql下一个版本应该且实现并不复杂增加的常用功能

    1.innodb的auto_increment应该在参考oracle的实现方式,定期持久化: 我们目前遇到个问题,出于性能考虑,我们每天会把当天处理完成的数据归到另外一张历史表,并清空,同时有可能会重 ...

  5. golang实现并发爬虫一(单任务版本爬虫功能)

    目的是写一个golang并发爬虫版本的演化过程. 那么在演化之前,当然是先跑通一下单任务版本的架构. 正如人走路之前是一定要学会爬走一般. 首先看一下单任务版本的爬虫架构,如下: 这是单任务版本爬虫的 ...

  6. CentOS以及Oracle数据库发展历史及各版本新功能介绍, 便于构造环境时有个对应关系

    CentOS版本历史 版本 CentOS版本号有两个部分,一个主要版本和一个次要版本,主要和次要版本号分别对应于RHEL的主要版本与更新包,CentOS采取从RHEL的源代码包来构建.例如CentOS ...

  7. spring和mybatis集成,自动生成model、mapper,增加mybatis分页功能

    软件简介 Spring是一个流行的控制反转(IoC)和面向切面(AOP)的容器框架,在java webapp开发中使用广泛.http://projects.spring.io/spring-frame ...

  8. LevelDB源码之五Current文件\Manifest文件\版本信息

    版本信息有什么用?先来简要说明三个类的具体用途: Version:代表了某一时刻的数据库版本信息,版本信息的主要内容是当前各个Level的SSTable数据文件列表. VersionSet:维护了一份 ...

  9. Apache Kafka 0.11版本新功能简介

    Apache Kafka近日推出0.11版本.这是一个里程碑式的大版本,特别是Kafka从这个版本开始支持“exactly-once”语义(下称EOS, exactly-once semantics) ...

  10. 在定制工作项时,把“团队项目”作为变量获取生成版本信息

    有用户最近提出这个需求: 通过工作项定制,新增一个字段用以保存项目Bug的"影响版本"信息,但是需要从当前团队项目的服务器生成纪录中获取版本的选项,类似默认模板中的"发现 ...

随机推荐

  1. Openharmony 跑 CV 应用

    最近有个项目,老同学让帮忙验证一个在ARM 板上跑 OpenHarmony,然后再集成一个CV算法上去,写这个文章主要是整理一下思路.如果有思路不对的地方,也烦请指出. 1. 个人做纯软件比较多,所以 ...

  2. .NET 压缩/解压文件

    本文为大家介绍下.NET解压/压缩zip文件.虽然解压缩不是啥核心技术,但压缩性能以及进度处理还是需要关注下,针对使用较多的zip开源组件验证,给大家提供技术选型 目前了解到的常用技术方案有Syste ...

  3. AI实战 | 领克汽车线上营销助手:全面功能展示与效果分析

    助手介绍 我就不自我介绍了,在我的智能体探索之旅中,很多人已经通过coze看过我的教程.今天,我专注于分享我所开发的一款助手--<领克汽车线上营销>. 他不仅仅是一个销售顾问的替身,更是一 ...

  4. [OI] 欢夏!邪龙?马拉车!

    标题来自原神 算法概述 Manacher 算法 用途:寻找回文串,最板子的情况下用于字符串的回文子串计数 给定一个字符串 \(S\),求出它全部的回文子串 容易想到一种暴力的 \(n^{2}\) 做法 ...

  5. 图片 电力电网行业IT运维方案

    智能电网背景下,电力.电网企业信息化逐渐渗透到其业务链的各个环节,云计算.物联网.移动互联网等新技术的应用,更驱动信息化与业务创新深度融合.电力.电网企业集团信息系统群逐渐朝着一体化方向发展,信息链越 ...

  6. Android USB 整条通知链分析

    以Android13 为例:在Android 13中,USB插入拔出事件的通知链从硬件层到应用层,依次经过硬件.内核.HAL.Framework.以及应用广播等多个模块,整个流程涉及的具体文件和逻辑如 ...

  7. kotlin更多语言结构——>异常

    异常类 Kotlin 中所有异常类都是 Throwable 类的子孙类.每个异常都有消息.堆栈回溯信息以及可选的原因 使用 throw-表达式来抛出异常 throw Exception("H ...

  8. kali Linux 启动 apache 和 mysqll

    kali linux 自带 apache 服务 和 mysql 服务 # 启动 apache 服务 service apache2 start # 启动 mysql 服务 service mysql ...

  9. AvaloniaTCP-v1.0.0:学习使用Avalonia/C#进行TCP通讯的一个简单Demo

    TCP通讯简介 TCP(传输控制协议,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议.它确保数据包按顺序传输,并在必要时进行重传,以保 ...

  10. ToDesk云电脑开启公测!支持AIGC、高性能渲染等场景,价格低至0.98元

    在云计算和人工智能技术飞速发展的今天,云电脑作为一种新型的计算模式,正逐渐改变着传统电脑的使用方式.近日,ToDesk云电脑宣布开启公测,以其支持AIGC(人工智能.大数据.云计算等技术的融合应用). ...