metadata 用于储存各种元信息
code错误码一般被用来进行异常传递,且需要具有携带message
文案信息的能力。
在这里,错误码被设计成Codes
接口,声明如下:
// 错误代码接口,其中包含代码和消息.
type Codes interface {
// 有时错误返回字符串形式的代码
// 注意:请勿在监控器报告中使用“error”,即使它现在也可以使用
Error() string
// 获取错误代码.
Code() int
// 获取错误信息.
Message() string
// 获取错误详细信息,可能为nil.
Details() []interface{}
}
// Code是int型错误代码规范.
type Code int
可以看到该接口一共有四个方法,且type Code int
结构体实现了该接口。
一个Code
错误码可以对应一个message
,默认实现会从全局变量_messages
中获取,业务可以将自定义Code
对应的message
通过调用Register
方法的方式传递进去,如:
cms := map[int]string{
0: "很好很强大!",
-304: "啥都没变啊~",
-404: "啥都没有啊~",
}
metacode.Register(cms)
fmt.Println(metacode.OK.Message()) // 输出:很好很强大!
注意:map[int]string
类型并不是绝对,比如有业务要支持多语言的场景就可以扩展为类似map[int]LangStruct
的结构,因为全局变量_messages
是atomic.Value
类型,只需要修改对应的Message
方法实现即可。
Details
接口为gRrc
预留,gRrc
传递异常会将服务端的错误码pb序列化之后赋值给Details
,客户端拿到之后反序列化得到,具体可阅读status
的实现:
code
包内的Status
结构体实现了Codes
接口grpc/status
包内包装了metacode.Status
和grpc.Status
进行互相转换的方法grpc
的client
和server
则使用转换方法将gRrc
底层返回的error
最终转换为metacode.Status
错误码转换有以下两种情况:
- 因为框架传递错误是靠
code
错误码,比如mvc框架返回的code
字段默认就是数字,那么客户端接收到如{"code":-404}
的话,可以使用mc := metacode.Int(-404)
或mc := metacode.String("-404")
来进行转换。 - 在项目中
dao
层返回一个错误码,往往返回参数类型建议为error
而不是metacode.Codes
,因为error
更通用,那么上层service
就可以使用mc := metacode.Cause(err)
进行转换。
错误码判断是否相等:
code
与code
判断使用:metacode.Equal(mc1, mc2)
code
与error
判断使用:metacode.EqualError(mc, err)
使用proto协议定义错误码,格式如下:
// user.proto
syntax = "proto3";
package code;
enum UserErrCode {
UserUndefined = 0; // 因protobuf协议限制必须存在!!!无意义的0,工具生成代码时会忽略该参数
UserNotLogin = 123; // 正式错误码
}
需要注意以下几点:
- 必须是enum类型,且名字规范必须以"ErrCode"结尾,如:UserErrCode
- 因为protobuf协议限制,第一个enum值必须为无意义的0
使用feo tool protoc --code user.proto
进行生成