开门见山
常量和常量文案场景
日常go业务开发中不可避免的会碰到定义一堆常量以及常量对应文案描述转换的需求,大概类似代码如下:
// 定义常量 const ( CodeErr = iota + 0 // 错误 CodeMsg // 提示 CodePwdError // 密码错误 CodeSuccess // 登录成功 ) // 定义错误码与描述信息的映射 var mapErrDesc = map[int]string{ CodeErr: "错误", CodeMsg: "提示", CodePwdError: "密码错误", CodeSuccess: "登录成功", } // 根据错误码返回描述信息 func GetDescription(errCode int) string { if desc, exist := mapErrDesc[errCode]; exist { return desc } return fmt.Sprintf("error code: %d", errCode) }
这种场景下拿到常量后需要转换为常量文案描述还得再使用一个map包裹然后调用函数进行转换,最致命的是每次添加常量需要同步改动好几处位置,稍不留意就是bug来了。
go generate简单介绍
go官方工具链提供有generate
工具指令,用于在go源码中通过特定注释语法书写一些编译前需要执行的指令,统一使用go generate
以执行这些指令。简单点儿理解就是:在go代码里通过注释书写编译前需要执行的命令,通过go generate
命令来统一执行这些命令。
要点如下:
-
源码里书写指令;写法:
//go:generate ls -ll
,本质上就是go源码的一段注释,//go:generate
为固定写法,不得有空格,ls -ll
即为需执行的指令,这个指令可以是任意存在的能执行的命令,这儿ls只是给一个示例; -
项目下终端执行:
go generate
,上述ls -ll
这个指令就会被执行; -
当然源码里
//go:generate xxx
注释指令是不限制数量的,然后执行顺序我这儿测试了下与包初始化顺序基本一致,最好不要依赖这个执行顺序;
官方英文介绍:https://github.com/golang/go/wiki/GoGenerateTools;命令行下帮助文档:go help generate
,会提到自动设置一些go相关的全局变量。
归纳一下go generate
的核心作用就是打包编译前用于汇总统执行指令。打包编译前需要执行的前置指令较多时直接通过特定注释语法配合go generate
可以达到统一汇总一条命令通行的目的,且因为前置指令书写在源码中,也可以跟随源码进行代码版本管理。
stringer指令
go官方提供有工具链:https://github.com/golang/tools/tree/master/cmd 用于开发效率提升。
其中有一个stringer工具,这个工具的介绍如下:
// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer // interface. Given the name of a (signed or unsigned) integer type T that has constants // defined, stringer will create a new self-contained Go source file implementing // func (t T) String() string // The file is created in the same package and directory as the package that defines T. // It has helpful defaults designed for use with go generate. // // Stringer works best with constants that are consecutive values such as created using iota, // but creates good code regardless. In the future it might also provide custom support for // constant sets that are bit patterns.
大概意思就是为INT型的自定义类型自动生成fmt.Stringer
的接口实现,即通过指定的语法规则自动生成interface
的实现。
-
定义一个基于INT类型(int、int64、uint均可)的定义类型,如:
type Code int
; -
罗列出所有自定义类型作为枚举值的常量值,如:
const ErrCode Code = iota + 1 // 错误
; -
终端执行指令:
stringer -type=Code -linecomment
即可自动为自定义Code
类型添加一个String
方法,即实现了fmt.Stringer
接口;
既然是工具肯定用之前需要先安装:
// 1.16之前老版本安装stringer工具 go get golang.org/x/tools/cmd/stringer // 1.16及其以后版本安装stringer工具 go install golang.org/x/tools/cmd/stringer@latest
比较溜的是stringer工具可以读取自定义类型常量值的后方注释内容作为String方法被调用时输出的文本内容;然后搭配上方关于generate指令的内容,一个自动生成常量和常量描述文案的方法就出来了。本示例生成的代码可以不用提交到代码仓库,打包编译前生成即可,而且后续添加新的常量也不再需要去维护常量文案映射的map,定义好常量和常量备注即可,解放双手解放思想,重复无技术含量且还可能潜在bug的问题交给稳定确切的工具即可。
本例在线示例代码:https://github.com/jjonline/study_golang/tree/master/gen
哟嚯,本文评论功能关闭啦~