Go 的链接器可以覆盖初始化的变量吗

sup*_*kas 5 go

来自ld 的文档

-X 符号值

设置未初始化的字符串变量的值。符号名称应采用 importpath.name 的形式,如“go tool nm”打印的符号表中所示。

所以这很酷。它允许你做这样的事情:

package main

import "fmt"

var version string

func main() {
    fmt.Println(version)
}
Run Code Online (Sandbox Code Playgroud)

编译:go build -ldflags '-X main.version 42' ...

我对他的功能有两个问题。首先,它也适用于初始化的字符串(例如var version = "bad build"),即使文档明确指出“否则未初始化的字符串变量”。

第二题是关于空格的。我的Makefile包含以下几行:

GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)

LDFLAGS := '-X main.version "$(GIT_BRANCH) $(GIT_COMMIT)"'
Run Code Online (Sandbox Code Playgroud)

命令的文档go说:

-ldflags 'flag list'

因此他们对所有链接器标志使用单引号。但是包含空格作为标志符号的字符串又如何呢-X?双引号工作得很好,顺便说一句,转义单引号也是如此,我只是不确定我是否可以依靠所有这些来一致地工作,因为文档没有提及任何内容。

第一个问题的澄清:

对所有变量进行零初始化。

文档说:-X symbol value Set the value of an otherwise uninitialized string variable [...].

意思是不是:

var foo string // only this one?
var bar = "bar" // or this one too, maybe
Run Code Online (Sandbox Code Playgroud)

One*_*One 2

引号由 shell(或 make)处理,所以是的,它是一致的。

调用程序填充 的go参数。

//编辑

要使用默认版本,您可以使用如下内容:

var version string

func init() {
    if len(version) == 0 {
        version = "master"
    }
}
Run Code Online (Sandbox Code Playgroud)

//编辑2

规格来看

当通过声明或调用 make 或 new 分配内存来存储值并且未提供显式初始化时,将为内存提供默认初始化。此类值的每个元素都设置为其类型的零值:对于布尔值为 false,对于整数为 0,对于浮点数为 0.0,对于字符串为"",对于指针、函数、接口、切片、通道和映射为 nil。