无论你今天怎么用力,明天的落叶还是会飘下来,世上有很多事是无法提前的,活在当下,正向提升。
1. 前言
开发中经常有定义错误码这样的需求,错误码唯一标识具体的错误信息。另外还需要设置每个错误的具体描述。比如在HTTP协议中,200表示 “OK”,404表示”Not Found”,那如何在我们的项目中添加这样的错误码呢?手动?还是自动?
2. 手动的情况
package main
import "fmt"
type ErrCode int
// 定义错误码
const (
ERR_OK ErrCode = iota //请求OK
ERR_PARAMS //请求参数出错
ERR_TiMEOUT //请求超时
)
// 定义错误码与描述信息的映射
var mapErrDesc = map[ErrCode]string {
ERR_OK: "OK",
ERR_PARAMS: "无效参数",
ERR_TiMEOUT: "超时",
}
//实现String() 这样print会调用String()
func (e ErrCode) String() string {
return GetDescription(e)
}
// 根据错误码返回描述信息
func GetDescription(errCode ErrCode) string {
if desc, exist := mapErrDesc[errCode]; exist {
return desc
}
return fmt.Sprintf("error code: %d", errCode)
}
func main() {
fmt.Println(ERR_TiMEOUT)
if ERR_OK == 0 {
fmt.Println(ERR_OK)
}
}
输出:
超时
OK
看到了吗,我们既可以拿错误码进行业务逻辑判断,又可以按照我们想要的方式输出,但是这样有个问题就是每次增加错误码时,都需要修改mapErrDesc,有时候可能会忘。另外,错误描述在注释和mapErrDesc都出现了。那么能不能只写注释,然后使用工具自动生成我们想要的代码呢?
3. 自动
package main
import "fmt"
type ErrCode int
//go:generate stringer -type ErrCode -linecomment -output code_string.go
const (
ERR_OK ErrCode = iota //请求OK
ERR_PARAMS//请求参数出错
ERR_TiMEOUT//请求超时
)
func main() {
fmt.Println(ERR_OK)
fmt.Println(ERR_PARAMS)
fmt.Println(ERR_TiMEOUT)
if ERR_OK == 0 {
fmt.Println(ERR_OK)
}
if ERR_TiMEOUT == 2 {
fmt.Println(ERR_TiMEOUT)
}
}
在同级目录下终端输入go generate
就会自动生成code_string.go,然后我们运行go run main.go
输出:
请求OK
请求参数出错
请求超时
请求OK
请求超时
go generate
是 Go 自带的工具。使用命令go generate执行。但是前提就是在你的错误码常量之前增加以下代码,如下所示:
//go:generate stringer -type ErrCode -linecomment -output code_string.go
go generate利用stringer生成字符串描述,默认stringer有两种模式,默认是根据变量/常量名来生成。
-
选项-type指定stringer命令作用的类型名,这里是ErrCode -
选项-output指定输出文件名,这里是code_string.go -
选项-linecomment指定后面的注释作为错误描述,比如”超时”
stringer可以自己安装,安装目录如下:
$ go get golang.org/x/tools/cmd/stringer
我们看下生成的code_string.go:
// Code generated by "stringer -type ErrCode -linecomment -output code_string.go"; DO NOT EDIT.
package main
import "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_OK-0]
_ = x[ERR_PARAMS-1]
_ = x[ERR_TiMEOUT-2]
}
const _ErrCode_name = "请求OK请求参数出错请求超时"
var _ErrCode_index = [...]uint8{0, 8, 26, 38}
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]]
}
我们看到它是节约存储错误码信息以及实现了String方法,这样就比我们自己实现好多了。
4. 小结
通过这种自动生成的方式,我们开发人员再也不用担心维护那么多错误码描述信息了,只要你的注释是ok的,那么你就直接使用错误码常量就行,哪里作为判断,哪里作为展示输出就特别方便了。
转载请注明:XAMPP中文组官网 » golang错误码再也不用维护了,代码放出来了