本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
大家在工作中定义错误码的时候都是如何处理的? xdm 可以评论区交流交流
我看到过有的是这样定义错误码的:
| 1 | go复制代码m := make(map[int]string) | 
还看到过这样定义错误码的:
| 1 | go复制代码type myErr struct { | 
也有见到过这样做的:
| 1 | go复制代码const ( | 
现在有一个更好的方法来实现我们工作中错误码的映射
引入 go generate
咱们引入 go generate ,可以只用定义错误码和写注释,就可以达到,当我们调用错误码的时候,能够正确的输出我们想要的错误信息
举个例子:
我们先建立如下目录,将错误码文件 errcode.go,放在一个单独的包里面
| 1 | shell复制代码. | 
我们还需要运用 stringer 工具,来辅助我们完成这个目标
| 1 | shell复制代码go get golang.org/x/tools/cmd/stringer | 
我们来看看上述文件的内容:
./mycodes/errcode.go
| 1 | shell复制代码/* | 
main.go
| 1 | shell复制代码/* | 
我们在 main.go 统计目录下初始化一下 go 的 模块, go mod init myerr
go.mod
| 1 | shell复制代码module myerr | 
开始演示
我们直接在 main.go 的同级目录下执行 go run main.go,输出如下:
| 1 | shell复制代码4 | 
是 ERR_CODE_CONN_REFUSE 对应的枚举值 4 ,可是我们期望的课不是这个,我们是期望能直接输出错误码对应的错误信息
使用 stringer
手动在 mycodes 目录下使用刚才安装的 stringer 工具
| 1 | shell复制代码stringer -linecomment -type ErrCode | 
此处的 ErrCode 是错误码的类型 , 执行上述语句后,mycodes 生成了一个文件 errcode_string.go ,现在目录结构是这样的
| 1 | shell复制代码. | 
看看 errcode_string.go 内容
| 1 | shell复制代码// Code generated by "stringer -linecomment -type ErrCode"; DO NOT EDIT. | 
我们可以看出 stringer 工具,将我们的错误码信息映射的字符串全部合并起来放在 _ErrCode_name 常量中,且有 _ErrCode_index 来作为每一个错误码映射字符串的索引值 ,最终便能实现错误码和字符串的映射,这个就很简单吧
效果展示
此时,我们仍然在 main.go 的同级目录下执行 go run main.go,输出如下:
| 1 | shell复制代码连接被拒绝 | 
显示的正式我们期望的错误信息
stringer 工具
我们来看看 stringer 工具的帮助,在来详细学习一波
| 1 | shell复制代码# stringer -h | 
可以看到大的用法有 2 种:
| 1 | shell复制代码 stringer [flags] -type T [directory] | 
第一种可以在类型 T 后面加上目录
第二种可以指定类型 T 后面指定明确的文件,但是这种方式必须是在一个单独的包里面
参数如下:
- -linecomment
使用行注释文本作为打印文本
- -output string
输出文件名称;默认源目录下的 / <类型> _string.go,所以我们可以看到例子中我们的输出文件在 mycodes 下的 errcode_string.go
- -trimprefix prefix
从生成的常量名称中修剪前缀
- -type string
以逗号分隔的类型名称列表,这个参数是必须要设置的
go generate
刚才我们是在命令行中,使用 stringer 工具来生成的,那么我们要把这些东西放入项目代码中就需要使用 go generate 工具了
先大致了解一下 go generate 是个啥玩意
go generate 是 go 自带的一个工具,我们可以通过在命令行中查看到:
| 1 | shell复制代码# go | 
咱们查看一下帮助文档 go help generate
| 1 | shell复制代码# go help generate | 
上面这些是 go generate 使用时候的环境变量
- $GOARCH
体系架构(arm、amd64 等)
- $GOOS
当前的 OS 环境(linux、windows 等)
- $GOFILE
当前处理中的文件名
- $GOLINE
当前命令在文件中的行号
- $GOPACKAGE
当前处理文件的包名
go generate命令格式
| 1 | shell复制代码go generate [-run regexp] [-n] [-v] [-x] [command] [build flags] [file.go... | packages] | 
| 1 | shell复制代码参数说明如下: | 
generate 用法
上面帮助文档有体现,我们可以使用  //go:generate command argument... 来讲 generate 工具用起来
实际案例
我们来简单的尝试一下
我们在刚才的 main.go 中加入 generate 的语句,使用 generate 执行,ls -alh
| 1 | shell复制代码/* | 
在 main.go 同级目录下执行 go generate 看效果
| 1 | shell复制代码# go generate | 
果然是调用 ls -alh 成功了
go generate + stringer 的使用
那么我们就把刚才我们实践的 stringer 工具也加进去玩玩
此时目录是这样的
| 1 | shell复制代码. | 
main.go 是这样的
| 1 | shell复制代码/* | 
没错我们加入了 //go:generate stringer -linecomment -type ErrCode ./mycodes
直接执行 go generate -x 来看效果吧
| 1 | shell复制代码# go generate -x | 
errcode_string.go 又生成了
| 1 | shell复制代码. | 
执行 go run main.go 当然必须是我们想要的东西啦
| 1 | shell复制代码# go run main.go | 
go generate 的使用规范
- 运行go generate命令时,才会执行特殊注释后面的命令
- 特殊注释必须以//go:generate开头,双斜线后面没有空格
- 该特殊注释必须在 .go 源码文件中
- 每个源码文件可以包含多个 generate 特殊注释
- 当go generate命令执行出错时,将终止程序的运行
最后说说 go generate 还能干些啥
go generate 能干的事情还真不少,只要是能够在 path 下面能找到的可执行程序,都可以放在 //go:generate 后面玩,一般使用 go generate 会有如下场景:
- protobuf:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件 , 这种情况 grpc 通信的时候常用
- yacc:从 .y 文件生成 .go 文件
- HTML:将 HTML 文件嵌入到 go 源码
- bindata:将形如 JPEG 这样的文件转成 go 代码中的字节数组
- Unicode:从 UnicodeData.txt 生成 Unicode 表
工具要用用起来才能体现它的价值
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是小魔童哪吒,欢迎点赞关注收藏,下次见~
本文转载自: 掘金