Go语言的链接器能否覆盖已初始化的变量?

huangapple go评论88阅读模式
英文:

Can Go's linker override initialized variables

问题

ld的文档中可以得知:

-X symbol value

设置一个本来未初始化的字符串变量的值。符号名称应该是importpath.name的形式,就像"go tool nm"打印的符号表中显示的那样。

所以这个功能非常酷。它允许你做这样的事情:

package main

import "fmt"

var version string

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

使用以下命令进行编译:go build -ldflags '-X main.version 42' ...

我有两个关于这个特性的问题。首先,即使文档明确说是"otherwise uninitialized string variable",它也适用于已初始化的字符串(例如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)"'

go命令的文档中说:

-ldflags 'flag list'

所以他们对所有链接器标志都使用单引号。但是对于作为-X标志的符号的字符串中的空格怎么处理呢?双引号可以正常工作,转义的单引号也可以,但是考虑到文档中没有提到这些内容,我不确定是否可以依赖这些内容的一致性。

对第一个问题的澄清:

Go会将所有变量进行零值初始化。

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

这是否意味着:

var foo string // 只有这个变量?
var bar = "bar" // 或者这个变量也是?
英文:

From ld's docs:

> -X symbol value
>
> Set the value of an otherwise uninitialized string variable. The symbol name should be of the form importpath.name, as displayed in the symbol table printed by "go tool nm".

So this is pretty cool. It allows you to do stuff like this:

package main

import "fmt"

var version string

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

Compile with: go build -ldflags '-X main.version 42' ...

I have two question about his feature. First of all it also works for initialized strings (e.g. var version = "bad build") even though the documentation specifically says "otherwise uninitialized string variable".

The seconds question is about spaces. My Makefile contains the following lines:

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)"'

The documentation for the go command says:

> -ldflags 'flag list'

So they're using single quotes for all linker flags. But what about a string containing spaces as symbol for the -X flag? The double-quotes work just fine, so do escaped single-quotes btw., I'm just not sure I can rely on all that to work consistently given the docs not mentioning any of it.

Clarification of the first question:

Go zero-initializes all vars.

The documentation says: -X symbol value Set the value of an otherwise uninitialized string variable [...].

Does this mean:

var foo string // only this one?
var bar = "bar" // or this one too, maybe

答案1

得分: 2

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

调用程序填充了go的参数。

//编辑

要使用默认版本,可以使用以下代码:

var version string

func init() {
    if len(version) == 0 {
        version = "master"
    }
}

//编辑2

根据规范

当分配内存来存储一个值时,无论是通过声明还是通过调用make或new,如果没有提供显式初始化,该内存都会被赋予默认初始化。这样的值的每个元素都被设置为其类型的零值:布尔类型为false,整数类型为0,浮点数类型为0.0,字符串类型为"",指针、函数、接口、切片、通道和映射类型为nil。

英文:

The quotes are handled by the shell (or make), so yes it's consistent.

The calling program populates go's args.

//edit

To use a default version you can use something like this:

var version string

func init() {
	if len(version) == 0 {
		version = "master"
	}
}

//edit 2

From the spec:

> When memory is allocated to store a value, either through a
> declaration or a call of make or new, and no explicit initialization
> is provided, the memory is given a default initialization. Each
> element of such a value is set to the zero value for its type: false
> for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil
> for pointers, functions, interfaces, slices, channels, and maps.

huangapple
  • 本文由 发表于 2014年9月13日 00:31:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/25812826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定