是否可以在每次编译Go应用程序时自动增加次要版本号?

我想在我的程序中设置一个版本号,使用一个自动递增的部分:

$ myapp -version
MyApp version 0.5.132

0.5是我设置的版本号,132是每次编译二进制文件时自动递增的值。

这在围棋中可能吗?


当前回答

另外,我想发布一个如何使用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

make文件将创建两个可执行文件。一个是执行函数1,另一个将函数2作为主要入口:

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

其他回答

在Windows操作系统上给出下面的程序

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%"

日期格式假设您的环境回声% Date %是Fri 07/22/2016,回声%time%是16:21:52.88

那么输出将是:version=0.0.1, date=2016-07-22T16:21:52

Go链接器(Go工具链接)有一个选项来设置一个未初始化的字符串变量的值:

- x importpath.name =值 将importpath named name中的字符串变量的值设置为

价值。 注意,在Go 1.5之前,这个选项有两个单独的参数。 现在它接受一个参数在第一个=号上分裂。

作为构建过程的一部分,您可以使用它设置版本字符串变量。您可以使用-ldflags将其传递给go工具。例如,给定以下源文件:

package main

import "fmt"

var xyz string

func main() {
    fmt.Println(xyz)
}

然后:

$ go run -ldflags "-X main.xyz=abc" main.go
abc

以定主。在构建时修改构建日期和时间:

go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go

如果编译时没有初始化main。以这种方式Minversion,它将包含空字符串。

使用ldflags设置主包中的变量:

使用文件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在非主包中设置变量:

使用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#including-build-information-in-the-executable


如果你正在使用goreleaser,请阅读https://goreleaser.com/environment/#using-the-mainversion:

默认的GoReleaser设置了三个ldflags: 主要。version:当前Git标签 main.commit:当前git提交SHA 主要。日期:根据RFC3339的日期


如果您想查看实际操作,请访问https://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go

另外,我想发布一个如何使用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

make文件将创建两个可执行文件。一个是执行函数1,另一个将函数2作为主要入口:

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

在其他答案的基础上,在最近的go版本中,也可以向ELF段编写buildid语句——尽管在程序中不太容易读取。

我写了相同的值给两者,使用如下的东西:

BuildInfo:= "BUILD #x, branch @ rev built yymmdd hh:mm:ss"
// note the nested quotes "''" required to get a string with 
// spaces passed correctly to the underlying tool
ldFl := fmt.Sprintf("-X 'main.buildId=%s' -s -w '-buildid=%s'", BuildInfo, BuildInfo)
args := []string{
    "build",
    "-ldflags", ldFl,
    "-trimpath",
    "-gcflags", "-dwarf=false",
}
buildpath:="path/to/my/cmd"
args=append(args,buildpath)
buildCmd:=exec.Command("go", args...)

我使用mage,一个用go编写的构建工具。您不需要上面的额外标志,但我选择这些标志是从发布二进制文件中尽可能多地剥离信息。

(题外话:与Make相比,Mage需要更多的前期工作,但比基于Make的构建系统更容易扩展/维护-另外,你不必在go和其他语法之间切换思维。)