Golang链接器(go build -ldflags) 与 go generate、go:embed的使用
链接器说人话很难解释这个定义索性不解释了从用途角度来解释允许你传递一些在编译时控制链接过程的选项或者说编译时嵌入一些变量如版本信息、构建时间戳等数据以例子来解释下面是一条命令mkdir-pbin/VERSION$(gitdescribe--tags--always)go build-ldflags-X main.Version$(VERSION)-o./bin/ ./...这种多条命令使用符号拼接起来不易于维护通常我们将它写在shell脚本里或者Makefile中当然这不是我们本文讨论重点下面以Makefile为例VERSION$(shell git describe--tags--always).PHONY:buildbuild:mkdir-p bin/go build-ldflags -X main.Version$(VERSION)-o ./bin/ ./...我们对上面命令进行说明# 在 shell 中执行 git describe --tags --always 并赋值给VERSION变量VERSION$(shellgitdescribe--tags--always)# git打印当前提交的tag标签在没有指定git的tag时一般为git log中前7位gitdescribe--tags--alwaysgo build-ldflags-X main.Version$(VERSION)-ldflags 设置链接器的标志-X 设置 Go 程序中变量的值-o ./bin/ # 指定输出的可执行文件的路径./… # 构建当前目录及其所有子目录中的Go代码// 下面是我们的程序体现 cmd/main.gopackagemainimport(fmt)var(Versionstring)funcmain(){ifVersion{Version1.0.1}fmt.Println(Version:,Version)}我们运行 go run main.go时输出永远都是Version: 1.0.1当我们执行make build后运行./bin/main时输出将会变成Version: 8b91e98通过Makefile里的go build命令和原始的go build 命令编译出来的包不同之处在于编译后的包嵌入了链接器功能将main.go中的Version变量进行了编译时赋值go generate扫描与当前包相关的源代码文件找出所有包含//go:generate的特殊注释提取并执行该特殊注释后面的命令用途: 用于初始化项目在编译/运行前所需要执行的命令格式: //go:generate 命令注意//与go之间没有空格上代码main.go//go:generate go run ../generate.gopackagemainfuncmain(){}终端执行go generate就会执行go run ../generate.go命令Wire依赖注入包就使用了此机制用来初始化包依赖//go:generate go run -modmod github.com/google/wire/cmd/wire//go:build !wireinject// build !wireinjectgo:embedembed与链接器类似编译时嵌入到代码中main.gopackagemainimport(_embedfmt)//go:embed data.txtvardatastringfuncmain(){fmt.Println(data)}data变量即是 data.txt 文本的内容