每次编译Go应用时,是否可以自动增加次要版本号?
我想在程序中设置一个带有自动递增部分的版本号:
$ myapp -version
MyApp version 0.5.132
我设置的版本号是0.5,而132则是每次编译二进制文件时都会自动增加的值。
Go中有可能吗?
每次编译Go应用时,是否可以自动增加次要版本号?
我想在程序中设置一个带有自动递增部分的版本号:
$ myapp -version
MyApp version 0.5.132
我设置的版本号是0.5,而132则是每次编译二进制文件时都会自动增加的值。
Go中有可能吗?
Answers:
Go链接器(go工具链接)具有一个选项,用于设置未初始化的字符串变量的值:
-X importpath.name=value Set the value of the string variable in importpath named name to
值。请注意,在Go 1.5之前,此选项采用两个单独的参数。现在,需要在第一个=符号上拆分一个参数。
作为构建过程的一部分,您可以使用此设置版本字符串变量。您可以go
使用来通过工具传递此信息-ldflags
。例如,给定以下源文件:
package main
import "fmt"
var xyz string
func main() {
fmt.Println(xyz)
}
然后:
$ go run -ldflags "-X main.xyz=abc" main.go
abc
为了main.minversion
在构建时设置构建日期和时间:
go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go
如果您不main.minversion
通过这种方式进行初始化而进行编译,则它将包含空字符串。
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
go build -ldflags "-X pkg.version=123"
不能 go build -ldflags "-X path/to/pkg.version=123"
按预期方式工作。希望能帮助到你。
另外,我想发布一个小例子,说明如何使用git和makefile:
--- Makefile ----
# This how we want to name the binary output
BINARY=gomake
# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --tags`
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS_f1=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f1"
LDFLAGS_f2=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f2"
# Builds the project
build:
go build ${LDFLAGS_f1} -o ${BINARY}_f1
go build ${LDFLAGS_f2} -o ${BINARY}_f2
# Installs our project: copies binaries
install:
go install ${LDFLAGS_f1}
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install
生成文件将创建两个可执行文件。一个正在执行功能一,另一个将执行功能二作为主要入口:
package main
import (
"fmt"
)
var (
Version string
Build string
Entry string
funcs = map[string]func() {
"f1":functionOne,"f2":functionTwo,
}
)
func functionOne() {
fmt.Println("This is function one")
}
func functionTwo() {
fmt.Println("This is function two")
}
func main() {
fmt.Println("Version: ", Version)
fmt.Println("Build Time: ", Build)
funcs[Entry]()
}
然后运行:
make
你会得到:
mab@h2470988:~/projects/go/gomake/3/gomake$ ls -al
total 2020
drwxrwxr-x 3 mab mab 4096 Sep 7 22:41 .
drwxrwxr-x 3 mab mab 4096 Aug 16 10:00 ..
drwxrwxr-x 8 mab mab 4096 Aug 17 16:40 .git
-rwxrwxr-x 1 mab mab 1023488 Sep 7 22:41 gomake_f1
-rwxrwxr-x 1 mab mab 1023488 Sep 7 22:41 gomake_f2
-rw-rw-r-- 1 mab mab 399 Aug 16 10:21 main.go
-rw-rw-r-- 1 mab mab 810 Sep 7 22:41 Makefile
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f1
Version: 1.0.1-1-gfb51187
Build Time: 2016-09-07T22:41:38+0200
This is function one
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f2
Version: 1.0.1-1-gfb51187
Build Time: 2016-09-07T22:41:39+0200
This is function two
-ldflags
在构建混合的命令行应用程序和库项目时,我在使用参数时遇到了麻烦,因此最终使用Makefile目标生成了包含应用程序的版本和构建日期的Go源文件:
BUILD_DATE := `date +%Y-%m-%d\ %H:%M`
VERSIONFILE := cmd/myapp/version.go
gensrc:
rm -f $(VERSIONFILE)
@echo "package main" > $(VERSIONFILE)
@echo "const (" >> $(VERSIONFILE)
@echo " VERSION = \"1.0\"" >> $(VERSIONFILE)
@echo " BUILD_DATE = \"$(BUILD_DATE)\"" >> $(VERSIONFILE)
@echo ")" >> $(VERSIONFILE)
在我的init()
方法中,我这样做:
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], VERSION)
fmt.Fprintf(os.Stderr, "built %s\n", BUILD_DATE)
fmt.Fprintln(os.Stderr, "usage:")
flag.PrintDefaults()
}
但是,如果您希望以原子方式增加内部版本号而不是内部版本日期,则可能需要创建一个包含最后内部版本号的本地文件。您的Makefile会将文件内容读入一个变量,对其进行递增,将其插入version.go
文件中而不是日期中,然后将新的内部版本号写回到该文件中。
ldflags
在main
包中设置变量:与文件main.go
:
package main
import "fmt"
var (
version string
build string
)
func main() {
fmt.Println("version=", version)
fmt.Println("build=", build)
}
然后运行:
go run \
-ldflags "-X main.version=1.0.0 -X main.build=12082019" \
main.go
建立:
go build -o mybinary \
-ldflags "-X main.version=1.0.0 -X 'main.build=$(date)'" \
main.go
ldflags
在non-main
包中设置变量:与文件config.go
:
package config
import "fmt"
var (
Version string
)
func LogVersion() {
fmt.Println("version=", Version)
}
您还将需要文件main.go
:
package main
import (
"fmt"
"github.com/user/repo/config"
}
func main() {
config.LogVersion()
}
首先构建二进制文件:
go build -o mybinary main.go
查找您要设置的变量名的完整路径:
go tool nm <path_to_binary> | grep Version
再次运行并构建二进制文件,但要使用ldflags
:
go run \
-ldflags "-X github.com/user/repo/config.Version=1.0.0" \
main.go --version
go build -o mybinary \
-ldflags "-X github.com/user/repo/config.Version=1.0.0" \
main.go
受https://github.com/golang/go/wiki/GcToolchainTricks#include-build-information-in-the-executable的启发
另外,如果您正在使用,请goreleaser
阅读以下https://goreleaser.com/#using-the-main-version:
默认明智的GoReleaser设置三个ldflags:
main.version:当前Git标签
main.commit:当前git commit SHA
main.date:日期符合RFC3339
如果您想在实际中看到它:https : //github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go
在Windows OS上,给出以下程序
package main
import "fmt"
var (
version string
date string
)
func main() {
fmt.Printf("version=%s, date=%s", version, date)
}
您可以使用构建
go build -ldflags "-X main.version=0.0.1 -X main.date=%date:~10,4%-%date:~4,2%-%date:~7,2%T%time:~0,2%:%time:~3,2%:%time:~6,2%"
日期格式假定你的环境echo %date%
是Fri 07/22/2016
和echo %time%
是16:21:52.88
然后输出将是: version=0.0.1, date=2016-07-22T16:21:52
go bouild
而不是将那个值保存到二进制文件中go run
?