使用 Go 管理版本的方法示例
简介
如果你曾经运行过dockerversion,
就会发现它提供了很多信息:
PSC:\Users\tzh>dockerversion Client:DockerEngine-Community Version:19.03.4 APIversion:1.40 Goversion:go1.12.10 Gitcommit:9013bf5 Built:ThuOct1723:44:482019 OS/Arch:windows/amd64 Experimental:false Server:DockerEngine-Community Engine: Version:19.03.4 APIversion:1.40(minimumversion1.12) Goversion:go1.12.10 Gitcommit:9013bf5 Built:ThuOct1723:50:382019 OS/Arch:linux/amd64 Experimental:false containerd: Version:v1.2.10 GitCommit:b34a5c8af56e510852c35414db4c1f4fa6172339 runc: Version:1.0.0-rc8+dev GitCommit:3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: Version:0.18.0 GitCommit:fec3683
对于编译好的二进制文件而言,获取版本信息是非常重要的.
尽可能地提供详细信息,有利于后期的维护和排错.
如何实现
对于版本信息等,有两种方式,
一种从外部获取,比如配置文件等,
另一种从源代码中获取,将配置信息写死在源代码中.
这两种都不太好,比如编译时间就不太好确定.
最好是能在gobuild时确定这些信息.
幸好,gobuild提供了一个选项叫做-ldflags'[pattern=]arglist'.
-Ximportpath.name=value Setthevalueofthestringvariableinimportpathnamednametovalue. Thisisonlyeffectiveifthevariableisdeclaredinthesourcecodeeitheruninitialized orinitializedtoaconstantstringexpression.-Xwillnotworkiftheinitializermakes afunctioncallorreferstoothervariables. NotethatbeforeGo1.5thisoptiontooktwoseparatearguments.
这使得我们可以在编译生成二进制文件时,指定某些变量的值.
比如我们有个文件是company/buildinfo包的一部分.
packagebuildinfo varBuildTimestring
运行gobuild-ldflags="-X'company/buildinfo.BuildTime=$(date)'"会记录编译时间,
将BuildTime的值设置为编译时的时间,即从$(date)中获取的时间.
参考:
Compilepackagesanddependencies
Commandlink
Includingbuildinformationintheexecutable
实践
新增pkg/version包,用于获取版本信息.
packageversion //这些值应该是从外部传入的 var( gitTagstring="" gitCommitstring="$Format:%H$"//sha1fromgit,outputof$(gitrev-parseHEAD) gitTreeStatestring="notagittree"//stateofgittree,either"clean"or"dirty" buildDatestring="1970-01-01T00:00:00Z"//builddateinISO8601format,outputof$(date-u+'%Y-%m-%dT%H:%M:%SZ') )
packageversion import( "fmt" "runtime" ) //构建时的版本信息 typeVersionInfostruct{ GitTagstring`json:"git_tag"` GitCommitstring`json:"git_commit"` GitTreeStatestring`json:"git_tree_state"` BuildDatestring`json:"build_date"` GoVersionstring`json:"go_version"` Compilerstring`json:"compiler"` Platformstring`json:"platform"` } func(infoVersionInfo)String()string{ returninfo.GitTag } funcGet()VersionInfo{ returnVersionInfo{ GitTag:gitTag, GitCommit:gitCommit, GitTreeState:gitTreeState, BuildDate:buildDate, GoVersion:runtime.Version(), Compiler:runtime.Compiler, Platform:fmt.Sprintf("%s/%s",runtime.GOOS,runtime.GOARCH), } }
主要定义了一个结构体,保持版本信息.
有些信息可以通过runtime获取,有些是编译时传进来的.
这里没有明确的版本号,而是使用gittag作为版本标签.
最后,定义一个命令version.
packagecmd import( "encoding/json" "fmt" "github.com/spf13/cobra" "tzh.com/web/pkg/version" ) varversionCmd=&cobra.Command{ Use:"version", Short:"Printtheversioninfoofserver", Long:"Printtheversioninfoofserver", Run:func(cmd*cobra.Command,args[]string){ printVersion() }, } funcprintVersion(){ info:=version.Get() infoj,err:=json.MarshalIndent(&info,"","")//加一点缩进 iferr!=nil{ fmt.Printf("遇到了错误:%v\n",err) } fmt.Println(string(infoj)) }
别忘了使用AddCommand添加子命令.
//初始化,设置flag等 funcinit(){ cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVarP(&cfgFile,"config","c","./conf/config.yaml","configfile(default:./conf/config.yaml)") rootCmd.AddCommand(versionCmd) }
由此,代码基本已经改完了,还剩下最后一点,修改Makefile文件,
以便简化操作过程.
修改Makefile
SHELL:=/bin/bash BASEDIR=$(shellpwd) #buildwithversioninfos versionDir="tzh.com/web/pkg/version" gitTag=$(shellif["`gitdescribe--tags--abbrev=02>/dev/null`"!=""];thengitdescribe--tags--abbrev=0;elsegitlog--pretty=format:'%h'-n1;fi) buildDate=$(shellTZ=UTCdate+%FT%T%z) gitCommit=$(shellgitlog--pretty=format:'%H'-n1) gitTreeState=$(shellifgitstatus|grep-q'clean';thenechoclean;elseechodirty;fi) ldflags="-w-X${versionDir}.gitTag=${gitTag}-X${versionDir}.buildDate=${buildDate}-X${versionDir}.gitCommit=${gitCommit}-X${versionDir}.gitTreeState=${gitTreeState}" all:gotoolbuild build: gobuild-ldflags${ldflags}./ run: gorun-ldflags${ldflags}./ docker: gorun-ldflags${ldflags}./-c./conf/config_docker.yaml
首行定义了运行的shell,默认是/bin/sh,这里改成了更常用的/bin/bash.
然后,就是定义了一大堆需要的参数.
在运行gobuild的时候添加了参数-ldflags${ldflags}.
如此,以后只要使用makebuild就能生成具有版本信息的二进制文件了.
编译好之后,可以运行./webversion查看具体的版本信息.
总结
通过为编译时添加额外信息,可以生成更具交互性的二进制文件.
同时,也能体会到Makefile带来的便捷.
当前部分的代码
作为版本v0.12.0
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。