专栏首页sunsky从外部设置传入Go变量

从外部设置传入Go变量

前提:必须在build/run时指定 -ldflags="-X main.a=2.0 -X main.b=1" , 且a,b必须是string的变量,不能是常量, 不能是struct.

CloudFlare的DNS服务器RRDNS是用Go编写的,DNS团队用于生成version.go在Makefile中调用的文件。version.go看起来像这样:

// THIS FILE IS AUTOGENERATED BY THE MAKEFILE. DO NOT EDIT.

// +build	make

package version

var (
	Version   = "2015.6.2-6-gfd7e2d1-dev"
	BuildTime = "2015-06-16-0431 UTC"
)

并用于在RRDNS中嵌入版本信息。它是用Makefile里建立sedgit describe从模板文件。它奏效了,但非常难看。

今天我们注意到数据团队CloudFlare的另一个Go团队使用-X链接器选项将更多版本号烘焙到二进制文件中。

可以设置的-X Go链接器选项设置-ldflags链接的Go程序中字符串变量的值。你这样使用它:-X main.version 1.0.0

一个简单的例子:假设您将此源文件另存为hello.go

package main

import "fmt"

var who = "World"

func main() {
    fmt.Printf("Hello, %s.\n", who)
}

然后你可以使用go run(或其他构建命令,如go buildgo install-ldflags来修改who变量的值:

$ go run hello.go
Hello, World.
$ go run -ldflags="-X main.who CloudFlare" hello.go
Hello, CloudFlare.

格式是importpath.name string,因此可以在Go程序中的任何位置设置任何字符串的值,而不仅仅是在main中。请注意,从Go 1.5开始,语法已更改importpath.name=string。旧样式仍然受支持,但链接器会抱怨。

我担心这不适用于外部链接(例如使用cgo时),但正如我们所看到的,-ldflags="-linkmode=external -v"Go链接器首先运行并且照顾我们的-X

$ go build -x -ldflags="-X main.who CloudFlare -linkmode=external -v" hello.go
WORK=/var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T/go-build149644699
mkdir -p $WORK/command-line-arguments/_obj/
cd /Users/filippo/tmp/X
/usr/local/Cellar/go/1.4.2/libexec/pkg/tool/darwin_amd64/6g -o $WORK/command-line-arguments.a -trimpath $WORK -p command-line-arguments -complete -D _/Users/filippo/tmp/X -I $WORK -pack ./hello.go
cd .
/usr/local/Cellar/go/1.4.2/libexec/pkg/tool/darwin_amd64/6l -o hello -L $WORK -X main.hi hi -linkmode=external -v -extld=clang $WORK/command-line-arguments.a
# command-line-arguments
HEADER = -H1 -T0x2000 -D0x0 -R0x1000
searching for runtime.a in $WORK/runtime.a
searching for runtime.a in /usr/local/Cellar/go/1.4.2/libexec/pkg/darwin_amd64/runtime.a
 0.06 deadcode
 0.07 pclntab=284969 bytes, funcdata total 49800 bytes
 0.07 dodata
 0.08 symsize = 0
 0.08 symsize = 0
 0.08 reloc
 0.09 reloc
 0.09 asmb
 0.09 codeblk
 0.09 datblk
 0.09 dwarf
 0.09 sym
 0.09 headr
host link: clang -m64 -gdwarf-2 -Wl,-no_pie,-pagezero_size,4000000 -o hello -Qunused-arguments /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/000000.o /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/000001.o /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/go.o -g -O2 -g -O2 -lpthread
 0.17 cpu time
33619 symbols
64 sizeof adr
216 sizeof prog
23412 liveness data

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go命令官方指南【原译】

    如果构建的参数是.go文件的列表,则build会将它们视为指定单个包的源文件列表。

    sunsky
  • go 1.11 模块和版本管理

    Go modules是go team在解决包依赖管理方面的一次勇敢尝试,无论如何,对Go语言来说都是一个好事。在本篇文章中,我们就一起来看看这个新引入的go m...

    sunsky
  • Go defer 会有性能损耗,尽量不要用?

    从结果上来,使用 defer 后的函数开销确实比没使用高了不少,这损耗用到哪里去了呢?

    sunsky
  • go语言

    goroot是go的安装目录,gopath是go语言的第三方库目录,需要添加环境变量GOPATH、GOROOT(安装时默认添加)

    sofu456
  • Golang之go 命令用法

    (注:实际上,package名在Go语言规范中指代码中“package”后使用的名称,此名称可以与文件夹名不同。默认生成的可执行文件名是文件夹名。)

    超蛋lhy
  • Go命令官方指南【原译】

    如果构建的参数是.go文件的列表,则build会将它们视为指定单个包的源文件列表。

    sunsky
  • 【从零开始学习Go语言】四.Go常用命令释义

    go run 命令用于编译并运行命令源码文件,如果你用vim编辑go文件并希望他暂时跑起来查看效果,使用此命令:go run file_name

    一只特立独行的兔先生
  • 【从零开始学习Go语言】四.Go常用命令释义

    go run 命令用于编译并运行命令源码文件,如果你用vim编辑go文件并希望他暂时跑起来查看效果,使用此命令:go run file_name

    一只特立独行的兔先生
  • 还在为Go依赖安装不上烦恼?

    打开VSCode后,新建一个xx.go文件,右下角会提示安装模块,选择install all:

    公众号guangcity
  • GO笔记之GO命令快速体验

    本文将在所能及的范围内,尽量地介绍GO提供的所有命令,从而实现对它们有个整体的认识。

    波罗学

扫码关注云+社区

领取腾讯云代金券