【问题标题】:using ldflags for giving binary file a version not working in golang使用 ldflags 为二进制文件提供一个在 golang 中不起作用的版本
【发布时间】:2023-02-02 10:14:01
【问题描述】:

main.go如下:

package main

func main() {
    println("hello world")
}

Makefile 如下:

flags=-X main.version=1.5.0

build:
    go build -ldflags "$(flags)" -o main main.go

然后我运行make,得到主文件。

在我运行 ./main -v 之后,我得到了:

hello world

为什么不显示1.5.0

go 版本是go version go1.18 darwin/arm64,当我运行 go version -m main 时,我得到:

main: go1.18
        path    command-line-arguments
        build   -compiler=gc
        build   -ldflags="-X main.version=1.5.0"
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=arm64
        build   GOOS=darwin

我对ldflags有误解。它的工作原理如下:

package main

import (
    "fmt"
    "os"
)

var (
    version string
)

func main() {
    args := os.Args
    if len(args) == 2 && (args[1] == "--version" || args[1] == "-v") {
        fmt.Printf("project version: %s \n", version)
        return
    }
}
$ ./main -v 
project version: 1.5.0

【问题讨论】:

  • 我找到了它不起作用的原因。我可以使用 os.Args 来接受 -v 标志。是对ldflags的误解。

标签: go


【解决方案1】:

您使用 ldflags (version) 设置的变量必须在包级别的包中声明。 -v的处理必须自己实现。

package main

import "flag"

var version string

func main() {
    var vFlag bool
    flag.BoolVar(&vFlag, "v", false, "show version")
    flag.Parse()
    
    if vFlag {
        println(version)
    } else {
        println("hello world")
    }
}
go build -ldflags "-X main.version=1.5.0" -o main main.go
./main -v
# 1.5.0
./main
# hello world

【讨论】:

    【解决方案2】:

    如果构建一个包(如go build github.com/xxx/yyy/zzz,则必须相应地为符号添加前缀。例如:

    go build 
        -ldflags "-X github.com/xxx/yyy/zzz/main.version=1.5.0" 
        -o my-awesome-app 
        github.com/xxx/yyy/zzz
    

    顺便提一句。确定要使用哪个符号 ID 的另一种方法是运行 nm 并为您要查找的变量运行 grep。

    【讨论】:

      【解决方案3】:

      此评论不是实际问题的答案,而是与标题相关。因此,我认为这里值得分享。

      ldflags 似乎不起作用的原因之一是它仅适用于字符串类型变量。

      例子:

      package main
      
      import "fmt"
      
      var sss = "FOO"
      var ccc = 2
      
      func main() {
              fmt.Println("variables:", sss, ccc)
      }
      
      • 使用go run main.go 执行此代码显示variables: FOO 2
      • go run -ldflags="-X main.sss=BAR" main.go执行它显示variables: BAR 2
      • go run -ldflags="-X main.ccc=5" main.go执行它显示main.ccc: cannot set with -X: not a var of type string (type.int)

      另一个问题是,如果缺少 -X ,您将不会收到任何错误消息。它只是不符合您的期望:

      • go run -ldflags="main.sss=BAR" main.go执行它显示variables: FOO 2

      【讨论】:

        猜你喜欢
        • 2015-06-17
        • 2011-05-23
        • 2016-04-16
        • 1970-01-01
        • 1970-01-01
        • 2020-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多