ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
`go generate`命令是在Go语言 1.4 版本里面新添加的一个命令,当运行该命令时,它将扫描与当前包相关的源代码文件,找出所有包含`//go:generate`的特殊注释,提取并执行该特殊注释后面的命令。 使用`go generate`命令时有以下几点需要注意: * 该特殊注释必须在 .go 源码文件中; * 每个源码文件可以包含多个 generate 特殊注释; * 运行`go generate`命令时,才会执行特殊注释后面的命令; * 当`go generate`命令执行出错时,将终止程序的运行; * 特殊注释必须以`//go:generate`开头,双斜线后面没有空格。 在下面这些场景下,我们会使用`go generate`命令: * yacc:从 .y 文件生成 .go 文件; * protobufs:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件; * Unicode:从 UnicodeData.txt 生成 Unicode 表; * HTML:将 HTML 文件嵌入到 go 源码; * bindata:将形如 JPEG 这样的文件转成 go 代码中的字节数组。 再比如: * string 方法:为类似枚举常量这样的类型生成 String() 方法; * 宏:为既定的泛型包生成特定的实现,比如用于 ints 的 sort.Ints。 `go generate`命令格式如下所示: go generate \[-run regexp\] \[-n\] \[-v\] \[-x\] \[command\] \[build flags\] \[file.go... | packages\] 参数说明如下: * \-run 正则表达式匹配命令行,仅执行匹配的命令; * \-v 输出被处理的包名和源文件名; * \-n 显示不执行命令; * \-x 显示并执行命令; * command 可以是在环境变量 PATH 中的任何命令。 执行`go generate`命令时,也可以使用一些环境变量,如下所示: * $GOARCH 体系架构(arm、amd64 等); * $GOOS 当前的 OS 环境(linux、windows 等); * $GOFILE 当前处理中的文件名; * $GOLINE 当前命令在文件中的行号; * $GOPACKAGE 当前处理文件的包名; * $DOLLAR 固定的`$`,不清楚具体用途。 【示例 1】假设我们有一个 main.go 文件,内容如下: ~~~ package mainimport "fmt"//go:generate go run main.go//go:generate go versionfunc main() { fmt.Println("http://c.biancheng.net/golang/")} ~~~ 执行`go generate -x`命令,输出结果如下: go generate -x go run main.go http://c.biancheng.net/golang/ go version go version go1.13.6 windows/amd64 通过运行结果可以看出`//go:generate`之后的命令成功运行了,命令中使用的`-x`参数是为了将执行的具体命令同时打印出来。 下面通过 stringer 工具来演示一下`go generate`命令的使用。 stringer 并不是Go语言自带的工具,需要手动安装。我们可以通过下面的命令来安装 stringer 工具。 go get golang.org/x/tools/cmd/stringer 上面的命令需要翻墙。条件不允许的话也可以通过 Github 上的镜像来安装,安装方法如下: git clone https://github.com/golang/tools/ $GOPATH/src/golang.org/x/tools go install golang.org/x/tools/cmd/stringer 安装好的 stringer 工具位于 GOPATH/bin 目录下,想要正常使用它,需要先将 GOPATH/bin 目录添加到系统的环境变量 PATH 中。 【示例 2】使用 stringer 工具实现 String() 方法: 首先,在项目目录下新建一个 painkiller 文件夹,并在该文件夹中创建 painkiller.go 文件,文件内容如下: ~~~ //go:generate stringer -type=Pillpackage painkillertype Pill intconst ( Placebo Pill = iota Aspirin Ibuprofen Paracetamol Acetaminophen = Paracetamol) ~~~ 然后,在 painkiller.go 文件所在的目录下运行`go generate`命令。 执行成功后没有任何提示信息,但会在当前目录下面生成一个 pill\_string.go 文件,文件中实现了我们需要的 String() 方法,文件内容如下: ~~~ 纯文本复制 ~~~ ~~~ // Code generated by "stringer -type=Pill"; DO NOT EDIT.package painkillerimport "strconv"func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[Placebo-0] _ = x[Aspirin-1] _ = x[Ibuprofen-2] _ = x[Paracetamol-3]}const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"var _Pill_index = [...]uint8{0, 7, 14, 23, 34}func (i Pill) String() string { if i < 0 || i >= Pill(len(_Pill_index)-1) { return "Pill(" + strconv.FormatInt(int64(i), 10) + ")" } return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]} ~~~