12.7 go generate命令 - Go语言中文社区

12.7 go generate命令


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命令格式如下所示:

  1. 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 文件,内容如下:

  1. package main
  2. import "fmt"
  3. //go:generate go run main.go
  4. //go:generate go version
  5. func main() {
  6. fmt.Println("http://c.biancheng.net/golang/")
  7. }

执行go generate -x命令,输出结果如下:

  1. - go generate -x
  2. - go run main.go
  3. - http://c.biancheng.net/golang/
  4. - go version
  5. - go version go1.13.6 windows/amd64

通过运行结果可以看出//go:generate之后的命令成功运行了,命令中使用的-x参数是为了将执行的具体命令同时打印出来。

下面通过 stringer 工具来演示一下go generate命令的使用。

stringer 并不是Go语言自带的工具,需要手动安装。我们可以通过下面的命令来安装 stringer 工具。

  1. go get golang.org/x/tools/cmd/stringer

上面的命令需要翻墙。条件不允许的话也可以通过 Github 上的镜像来安装,安装方法如下:

  1. git clone https://github.com/golang/tools/ $GOPATH/src/golang.org/x/tools
  2. go install golang.org/x/tools/cmd/stringer

安装好的 stringer 工具位于 GOPATH/bin 目录下,想要正常使用它,需要先将 GOPATH/bin 目录添加到系统的环境变量 PATH 中。

【示例 2】使用 stringer 工具实现 String() 方法:

首先,在项目目录下新建一个 painkiller 文件夹,并在该文件夹中创建 painkiller.go 文件,文件内容如下:

  1. //go:generate stringer -type=Pill
  2. package painkiller
  3. type Pill int
  4. const (
  5. Placebo Pill = iota
  6. Aspirin
  7. Ibuprofen
  8. Paracetamol
  9. Acetaminophen = Paracetamol
  10. )

然后,在 painkiller.go 文件所在的目录下运行go generate命令。

执行成功后没有任何提示信息,但会在当前目录下面生成一个 pill_string.go 文件,文件中实现了我们需要的 String() 方法,文件内容如下:

  1. // Code generated by "stringer -type=Pill"; DO NOT EDIT.
  2. package painkiller
  3. import "strconv"
  4. func _() {
  5. // An "invalid array index" compiler error signifies that the constant values have changed.
  6. // Re-run the stringer command to generate them again.
  7. var x [1]struct{}
  8. _ = x[Placebo-0]
  9. _ = x[Aspirin-1]
  10. _ = x[Ibuprofen-2]
  11. _ = x[Paracetamol-3]
  12. }
  13. const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"
  14. var _Pill_index = [...]uint8{0, 7, 14, 23, 34}
  15. func (i Pill) String() string {
  16. if i < 0 || i >= Pill(len(_Pill_index)-1) {
  17. return "Pill(" + strconv.FormatInt(int64(i), 10) + ")"
  18. }
  19. return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
  20. }
版权声明:本教程内容除了本站原创内容外,还有来源自C语言编程网,博客园,CSDN等技术站点,感谢相关博主原创文章,转载请附上原文出处链接和本声明。
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 阅读 ( 612 )
  • 分类:Go

0 条评论

官方社群

GO教程

猜你喜欢