Golang Generate命令说明与使用

前期有专门利用 go generate 自动生成 Go 代码,今日在查看 Go 源代码时发现有大量使用此命令已生成各类代码。故在此特写文章说明 generate 命令的神奇之处。期有专门利用 go generate 自动生成 Go 代码,今日在查看 Go 源代码时发现有大量使用此命令已生成各类代码。故在此特写文章说明 generate 命令的神奇之处。

命令诉求

通用计算有一特性——图灵完备。是一个计算机程序能编写一个计算机程序。既能写程序的程序。按规则定义描述内容,则可以根据描述生成程序代码。10年时刚做项目便以增删改查为主,代码生成器生成代码那是杠杠的。
通过定义便可高效生成代码,无需手工编码。如当定义一个枚举后,为了打印友好内容,我们经常手工定义 String 方法。

遇到枚举调整时,则必须要再同步修改 statusText,而此事常容被忽视。

Generate 命令说明

早在 Go1.4 版本实现,所以你现在可以看到 Go 源码中大量含有的该命令使用。
如:在 unicode 包中生产 Unicode 表,为encoding/gob创建有效的编解码方法,在 time 包中创建时区数据等等
go generate 用于一键式批量执行任何命令,创建或更新Go文件或者输出结果。
Generate 命令和其他go build、go get、go test等没半毛钱关系。需特定执行,命令如下:

参数说明:

  • -run 正则表达式匹配命令行,仅执行匹配的命令
  • -v 打印已被检索处理的文件。
  • -n 打印出将被执行的命令,此时将不真实执行命令
  • -x 打印已执行的命令

执行举例:

如何使用Generate命令

需在的代码中配置 generate 标记,则在执行 go generate 时可被检测到。go generate 执行时,实际在扫描如下内容:

generate 命令不是解析文件,而是逐行匹配以 

//go:generate 开头的行(前面不要有空格)。故命令可以写在任何位置,也可存在多个命令行。
//go:generate 后跟随具体的命令。命令为可执行程序,形同在 Shell 下执行。所以命令是在环境变量中存在,也可是完整路径。如:

执行:

在执行 go generate 时将会加入些信息到环境变量,可在命令程序中使用。

同时该命令是在所处理文件的目录下执行,故利用上述信息和当前目录,边可获得丰富的DIY功能。

Generate实战

如前面所述,现在练手来实现对枚举String函数以打印友好信息。 最终调用为:

自动生成如下代码:

业务逻辑

该如何实现呢?实际我们需要获得三项:

  • 包名:user,该文件将存放在当前目录,需要知晓包名称
  • 类型名:Status,参数传递
  • 所有同类型var: Offline,Online,Disable,Deleted

再生成代码后将其保存到当前目录,同时进行gofmt。

具体实现

1.通过环境变量获取包名称

2.获取当前目录包信息 这里利用Go内置的库go/build解析目录,则可以获得该文件夹下包信息。

至此便能获得目录下所有 Go文件 pkgInfo.GoFiles,用于语法树解析。

3.解析 Go 文件语法树,提取Status相关信息。 需要注意的是,我们约定所定义的枚举信息实际应该全部是 Const。需从语法树中 提取出所有的 Const,并判断类型是否符合条件。
这里利用的是 Go 的语法树库 go/ast(abstract syntax tree) 和解析库 go/parser,语法树是按语句块 () 形成树结构。从中过滤 const 语句块

再循环const语句块中最小部分:

对每小部分判断,并获得对应的 Type,如果 Type 为空则同上一行的一致。

行内容

但我们只需要获得符合要求的 Type,获得符合要求的 Const 信息:

这里的typesMap是根据程序入参建立:

4.根据收集的Const,生成String函数
使用模板生成内容,同时进行gofmt

5.保存代码到文件 将文件直接保存到当前目录下,文件名已”_string”结尾

6.在status.go源文件配置标记

运行go generate,出现错误:

此时需要将myenumstr.go install

安装后,我们可以在status.go使用两种方式调用:

至此写完,完整代码如下:

源代码-user.go

源代码-myenumstr.go

实现该功能,查看具体stringer文档(https://godoc.org/golang.org/x/tools/cmd/stringer

作者:虞双齐

原文链接:https://yushuangqi.com/

文章分类 未分类

发表评论

电子邮件地址不会被公开。

在线交流

数百位业内高手和同行在等你交流
Reboot运维开发分享