介绍

go generate命令是go 1.3版本里面新添加的一个命令,当运行go generate时,它将扫描与当前包相关的源代码文件,找出所有包含”//go:generate”的特殊注释,提取并执行该特殊注释后面的命令,命令为可执行程序,形同shell下面执行。
有几点需要注意:

  • 该特殊注释必须在.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命令使用格式如下:

  1. go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

其中:

  • -run 正则表达式匹配命令行,仅执行匹配的命令
  • -v 输出被处理的包名和源文件名
  • -n 显示不执行命令
  • -x 显示并执行命令

执行go generate时,有一些环境变量可以使用:

  1. $GOARCH
  2. 体系架构 (armamd64等待)
  3. $GOOS
  4. OS环境(linuxwindows等)
  5. $GOFILE
  6. 当前处理中的文件名
  7. $GOLINE
  8. 当前命令在文件中的行号
  9. $GOPACKAGE
  10. 当前处理文件的包名
  11. $DOLLAR
  12. 固定的"$",不清楚用途

例子:

假设我们有个main.go文件,内容如下:

  1. package main
  2. import "fmt"
  3. //go:generate echo hello
  4. //go:generate go run main.go
  5. //go:generate echo file=$GOFILE pkg=$GOPACKAGE
  6. func main() {
  7. fmt.Println("main func")
  8. }

执行“go generate”后,输出如下:

  1. $ go generate
  2. hello
  3. main func
  4. file=main.go pkg=main