简介
应用程序部署到生产环境中时,版本信息、日志和调试过程,增加识别信息应用程序的构建信息。
版本信息通常包括高度动态的数据,因为这些值是不断变化的,将这些数据直接编码到源代码中,并在每次新的构建之前进行修改,是很繁琐的,而且容易出错:源文件可能会移动,变量/
常量在整个开发过程中可能会随着切换文件而改动,打断构建过程。
Go 中解决这个问题的一个方法是在使用 go build 命令时加上 -ldflags
,在构建时将动态信息插入二进制文件中,而不需要修改源代码。
这个标志中,ld 代表 linker
,这个程序将编译后的源代码的不同部分连接成最终的二进制文件。
范例应用程序
package main
import (
"fmt"
)
var Version = "development"
func main() {
fmt.Println("Version:\t", Version)
}
go build 中使用 ldflags 的方法
我们将使用-X标志在链接时将信息写入变量,跟着的是参数的 package 路径和它的新值:
D:\GUI>go build -ldflags="-X 'main.Version=v1.0.0'"
D:\GUI>cc.exe
Version: v1.0.0
D:\GUI>
在引号内,现在有 X 选项和一个键值对,代表要改变的变量和它的新值。
.
字符将包路径和变量名称分开,单引号用于避免键值对被断开。
锁定子包变量
D:\GUI\go.mod
module cc
go 1.20
D:\GUI\build\build.go
package build
var Time string
var User string
Time 变量将保存二进制文件建立的时间的字符串表示。
User 变量将保存构建二进制文件的用户名称。
由于这两个变量总是有值,你不需要像对 Version 那样用默认值初始化这些变量。
D:\GUI\cc.go
package main
import (
"cc/build"
"fmt"
)
var Version = "development"
func main() {
fmt.Println("Version:\t", Version)
fmt.Println("build.Time:\t", build.Time)
fmt.Println("build.User:\t", build.User)
}
Go 工具链中的nm命令。
go tool nm命令将输出在给定的可执行文件、对象文件或存档中涉及的符号。
在这种情况下,符号指的是代码中的一个对象,例如一个定义的或导入的变量或函数。
通过使用 nm 生成一个符号表,并使用 grep 搜索一个变量,你可以快速找到其路径信息。
注意:如果软件包名称中有任何非 ASCII 字符,或者有 " 或 % 字符,nm 命令将不能帮助你找到变量的路径,因为这是工具本身的限制。
要使用这个命令,首先要为 app 构建二进制文件:
go build
现在app已经构建好了,将nm工具指向它,并在输出中搜索:
go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"
在 Windows 命令提示符中,你不能直接在传递给 -ldflags
标志的字符串内部使用诸如 date
和 id
之类的 shell 命令。相反,你需要在构建过程中提供实际的值。
以下是如何修改你的命令以实现预期结果:
D:\GUI>go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'cc/build.User=%USERNAME%' -X 'cc/build.Time=%DATE% %TIME%'"
cc
D:\GUI>cc.exe
Version: v1.0.0
build.Time: 2023/08/12 周六 21:59:05.05
build.User: ASUS
D:\GUI>
在这个命令中:
%USERNAME%
将会被当前用户名替代。%DATE% %TIME%
将会被当前日期和时间替代。
构建应用程序之后,你应该在输出中看到正确的值。