go generate命令

格式:

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

说明:

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

注释实例:

//go:generate command arg1 arg2

简介

  • 官网文档 [3]

  • go generate命令是go 1.4版本里面新添加的一个命令

  • 当运行go generate时,它将扫描与当前包相关的源代码文件:

    1. 找出所有包含"//go:generate"的特殊注释,提取并执行该特殊注释后面的命令
    2. 命令为可执行程序,形同shell下面执行
    

有几点需要注意:

1. 该特殊注释必须在.go源码文件中
2. 每个源码文件可以包含多个generate特殊注释时
3. 显示运行go generate命令时,才会执行特殊注释后面的命令
4. 命令串行执行的,如果出错,就终止后面的执行
5. 特殊注释必须以"//go:generate"开头,双斜线后面没有空格

应用场景:

1. yacc:从 .y 文件生成 .go 文件
2. protobufs:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件
3. Unicode:从 UnicodeData.txt 生成 Unicode 表
4. HTML:将 HTML 文件嵌入到 go 源码
5. bindata:将形如 JPEG 这样的文件转成 go 代码中的字节数组

其他应用场景:

1. string方法:为类似枚举常量这样的类型生成String()方法。
2. 宏:为既定的泛型包生成特定的实现,比如用于ints的sort.Ints。

Warning

go:generate前面只能使用//注释,且//与go:generate之间不能有空格!!!

使用

基本:

//go:generate stringer -type ErrCode

选项-type指定stringer命令作用的类型名
在同一个目录下生成一个文件errcode_string.go
文件名格式是类型名小写_string.go

指定输出文件名:

//go:generate stringer -type ErrCode -output code_string.go

-linecomment选项:

//go:generate stringer -type ErrCode -linecomment -output code_string.go

实例1

源码:

package main

import "fmt"

//go:generate echo hello
//go:generate go run main.go
//go:generate  echo file=$GOFILE pkg=$GOPACKAGE
func main() {
    fmt.Println("main func")
}

go generate:

$ go generate
hello
main func
file=main.go pkg=main

实例2

源码:

//go:generate stringer -type=Pill
package painkiller

type Pill int

const (
    Placebo Pill = iota
    Aspirin
    Ibuprofen
    Paracetamol
    Acetaminophen = Paracetamol
)

安装stringer:

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

$ go generate:

$ cat pill_string.go   // 生成这么一个文件
// Code generated by "stringer -type=Pill"; DO NOT EDIT.
package painkiller
import "fmt"

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 fmt.Sprintf("Pill(%d)", i)
    }
    return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
}