概述

golang tools 是官方提供的工具集,是 Gophers 的工具宝库,值得好好探索一番,参见 GitHub,文档地址。里面有丰富的开发辅助工具,所有的 Go 开发插件都离不开这些工具的支持。例如goimports工具自动导入使用的包,去掉未使用的包;gorename用来重命名标识符。

今天要使用的stringer工具也在tools工具包中。

命令描述如下:

go help generateusage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]Generate runs commands described by directives within existing
files. Those commands can run any process but the intent is to
create or update Go source files.Go generate is never run automatically by go build, go get, go test,
and so on. It must be run explicitly.Go generate scans the file for directives, which are lines of
the form,//go:generate command argument...(note: no leading spaces and no space in "//go") where command
is the generator to be run, corresponding to an executable file
that can be run locally. It must either be in the shell path
(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
command alias, described below....

总的说来 go generate 允许你在 go 代码中来运行当前系统中已安装的程序,原则上你可以运行任何程序,但是此命令设计的初衷是用来创建或者更新go源码文件。
如果要执行的程序不在环境变量中,则需要写全路径。
必须手动执行 go generate,才会去解析执行 generate 指令,并且 go generate 命令不会执行go源代码。
单个运行只需要在对应目录(包)下执行:go generate
对应有多个目录,且又有多个generate需要执行的,在最上层目录下运行:go generate ./…

一个简单的例子:

package mainimport "fmt"//go:generate echo hellofunc main() {fmt.Println("Hello world!")
}

在linux系统上运行 go generate
输出 hello
就相当于你直接运行 echo hello

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

使用场景

  1. 在build之前生成一些特定文件(下文介绍)。
  2. yacc:从 .y 文件生成 .go 文件。
  3. protobufs:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件。
  4. Unicode:从 UnicodeData.txt 生成 Unicode 表。

注意事项

  1. 必须在.go源码文件中。
  2. 每个源码文件可以包含多个generate特殊注释。
  3. 显示运行go generate命令时,才会执行特殊注释后面的命令。
  4. 如果前面的注释执行出错,则终止执行。
  5. //与go:generate之间不能有空格。

可以使用的环境变量

$GOARCH:体系架构 (arm、amd64等)
$GOOS:OS环境(linux、windows等)
$GOFILE:当前处理中的文件名
$GOLINE:当前命令在文件中的行号
$GOPACKAGE:当前处理文件的包名
$DOLLAR:美元符号

在开发API Server的时候我们需要去定义一些错误码及其描述,每次定义错误码的时候,同时需要添加描述信息。而且描述信息经常会忘。比如:
errcode.go

package maintype ErrCode int//go:generate stringer -type ErrCode
const (ERR_CODE_OK             ErrCode = 0 // OKERR_CODE_INVALID_PARAMS ErrCode = 1 // 无效参数ERR_CODE_TIMEOUT        ErrCode = 2 // 超时
)func main() {fmt.Println(ERR_CODE_INVALID_PARAMS)
}

然后我想使用 go generate 来替我生成描述文件。

安装 stringer 程序:go get golang.org/x/tools/cmd/stringer

stringer命令可以为给定类型生成String方法。

stringer有两种模式,默认是根据变量/常量名来生成字符串描述。我们在常量定义上增加注释:

//go:generate stringer -type ErrCode

选项-type指定stringer命令作用的类型名。

然后在同一个目录下执行:
go generate

会在同一个目录下生成一个文件 errcode_string.go 文件名格式是类型名小写 _string.go。也可以通过 -output 选项指定输出文件名,例如下面就是指定输出文件名为 code_string.go

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

我们来看看这个文件的内容:

// Code generated by "stringer -type ErrCode"; DO NOT EDIT.package mainimport "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[ERR_CODE_OK-0]_ = x[ERR_CODE_INVALID_PARAMS-1]_ = x[ERR_CODE_TIMEOUT-2]
}const _ErrCode_name = "ERR_CODE_OKERR_CODE_INVALID_PARAMSERR_CODE_TIMEOUT"var _ErrCode_index = [...]uint8{0, 11, 34, 50}func (i ErrCode) String() string {if i < 0 || i >= ErrCode(len(_ErrCode_index)-1) {return "ErrCode(" + strconv.FormatInt(int64(i), 10) + ")"}return _ErrCode_name[_ErrCode_index[i]:_ErrCode_index[i+1]]
}

因为 fmt 包中的很多方法会自动优先调用 String() 方法,所以 fmt.Println(ERR_CODE_INVALID_PARAMS) 将会输出 1,但是我们想要的是后面的注释文本,修改指令
//go:generate stringer -type ErrCode -linecomment

调用 go generate 重新生成

// Code generated by "stringer -type ErrCode -linecomment"; DO NOT EDIT.package mainimport "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[ERR_CODE_OK-0]_ = x[ERR_CODE_INVALID_PARAMS-1]_ = x[ERR_CODE_TIMEOUT-2]
}const _ErrCode_name = "OK无效参数超时"var _ErrCode_index = [...]uint8{0, 2, 14, 20}func (i ErrCode) String() string {if i < 0 || i >= ErrCode(len(_ErrCode_index)-1) {return "ErrCode(" + strconv.FormatInt(int64(i), 10) + ")"}return _ErrCode_name[_ErrCode_index[i]:_ErrCode_index[i+1]]
}

此时 fmt.Println(ERR_CODE_INVALID_PARAMS) 将会输出 无效参数,符合预期。

生成的代码做了一些优化,减少了字符串对象的数量。

现在你就不用担心添加了错误码而忘记添加错误信息了。

每次编译都需要先运行 go generate 貌似有点麻烦,可以写到 shell 文件。

go generate 的用法相关推荐

  1. 【IEEE_Verilog-12.4】generate的用法

    12.4 Generate construct generate构造用于在模型中有条件地或实例化的生成块.生成块是一个或多个模块项的集合.一个生成块不能包含端口声明.参数声明.指定块或specpara ...

  2. Verilog中generate的用法

    Generate 语句基本概念 generate 语句可以动态地生成 Verilog 代码,常用于编写许多结构相同但参数不同的赋值语句或逻辑语句,方便参数化模块的生成.generate 语句主要有以下 ...

  3. Verilog的generate的用法

    生成语句可以动态的生成verilog代码,当对矢量中的多个位进行 重复操作 时,或者当进行多个模块的实例引用的重复操作时,或者根据参数的定义来确定程序中是否应该包含某段Verilog代码的时候,使用生 ...

  4. Verilog中generate语句的用法

    在Verilog-2001中新增了语句generate,通过generate循环,可以产生一个对象(比如一个元件或者是一个模块)的多次例化,为可变尺度的设计提供了方便,generate语句一般在循环和 ...

  5. Verilog中generate语法和作用

    Verilog中generate语句的用法 在Verilog-2001中新增了语句generate,通过generate循环,可以产生一个对象(比如一个元件或者是一个模块)的多次例化,为可变尺度的设计 ...

  6. 详解go generate

    我时不时得会在别人的代码中看到"go generate",也大致知道这有什么作用,但是平时写写业务代码,并没有过多关注这方面的知识.今天得闲,稍微研究下. go generate的 ...

  7. 【Verilog我思我用】-generate

    [Verilog我思我用]-generate 在使用xilinx官方例程<XAPP585>实现CameraLink接口发送或者接收数据时,有个程序还是值得学习的,下面把这段程序截出来: g ...

  8. 一把王者的时间,学会generate语句【Verilog高级教程】

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  9. 源码安装Bind 9.10 正式版 开启DLZ数据库支持 和 数据库view查询

    昨天看见新闻,说Bind 9.10.3版本已经正式发布了,迫不及待安装试试,,, 我前面的文章已经体验过 bind 9.10的RC版的个别新功能, 见文 Bind 9.10 源码安装 以及 新增red ...

最新文章

  1. 湘潭大学网络编程_湘潭大学计算机学院网络空间安全学院“湘韵”研究生论坛成功举行...
  2. 尝鲜.net core2.1 ——编写一个global tool
  3. EnjoyingSoft之Mule ESB开发教程第六篇:Data Transform - 数据转换
  4. linux的mysql小记
  5. 卡顿严重_微软Win 10游戏模式致《使命召唤:战区》等游戏出现严重卡顿现象
  6. 大数据之统计学基础(一)
  7. mysql修改引擎_修改MySQL引擎
  8. linux服务器配置python环境_服务器python环境配置福利,CentOS ,Linux 一键下载python3和环境配置...
  9. spingMVC 请求参数绑定
  10. UITextField 对比 UITextView
  11. [转载]幂等和高并发在电商系统中的使用
  12. HackFifteen 移除背景以提升Activity启动速度
  13. arcmap 影像坐标批处理 python_ArcMap怎么把坐标系转换成投影坐标系?
  14. 多层陶瓷电容器用处_陶瓷电容器的作用有哪些?
  15. 终有一天,你没法成为曾经梦里的那个人了。
  16. 身在北京,都有故事:九位北漂的心酸故事,只有经历过才有体会!
  17. 无力吐槽的废酱的几个问题
  18. windows环境下利用python进行CGI配置
  19. java gravity_Android属性gravity与layout_gravity的区别
  20. 单键模式_购买单键或更换整个键盘是否更好?

热门文章

  1. python fixture_使用Fixture
  2. 常用linux环境配置大全
  3. 灵活而奇特的C++语言特性——统一初始化
  4. 使用python软件如何关闭弹窗_如何通过按钮关闭Kivy弹出窗口?
  5. 双击vs解决方案打不开
  6. Istio四之故障注入和链路追踪
  7. 数据存储技术复习(一)未完
  8. jsignature插件实操,完成手写签名图片格式功能
  9. 九宫格多级OLED(LCD)菜单
  10. 计算机系统的性能建模与设计 排队理论,基于排队论的UM-BUS总线性能建模与评价-计算机科学.PDF...