package errors import ( "fmt" "sync" ) type Coder interface { // HTTPStatus 返回http状态码 HTTPStatus() int // String 展示给外部用户的错误信息 String() string // Reference 展示给用户解决错误需要参开的引用文档 Reference() string // Code 错误码 Code() int } // 错误码映射 var codes = map[int]Coder{} var codeMux = &sync.Mutex{} // Register 注册错误码,存在会被覆盖 func Register(coder Coder) { if coder.Code() == 999999 { panic("code `999999` is reserved by system as unknownCode error code") } codeMux.Lock() defer codeMux.Unlock() codes[coder.Code()] = coder } // MustRegister 注册错误码,已注册报错 func MustRegister(coder Coder) { if coder.Code() == 999999 { panic("code `999999` is reserved by system as unknownCode error code") } codeMux.Lock() defer codeMux.Unlock() if _, ok := codes[coder.Code()]; ok { panic(fmt.Sprintf("code: %d already exist", coder.Code())) } codes[coder.Code()] = coder } // ParseCoder 解析错误码 // 将错误解析为 *withCode 类型。如果原生错误不是本错误包生成,返回未知错误 func ParseCoder(err error) Coder { if err == nil { return nil } if v, ok := err.(*withCode); ok { if coder, ok := codes[v.code]; ok { return coder } } return unknownCoder } // IsCode 判断错误码是否在当前错误链中 func IsCode(err error, code int) bool { if v, ok := err.(*withCode); ok { if v.code == code { return true } if v.cause != nil { return IsCode(v.cause, code) } return false } return false }