bilibili-backup/library/ecode/ecode.go
2019-04-22 02:59:20 +00:00

124 lines
2.4 KiB
Go

package ecode
import (
"fmt"
"strconv"
"sync/atomic"
"github.com/pkg/errors"
)
var (
_messages atomic.Value // NOTE: stored map[string]map[int]string
_codes = map[int]struct{}{} // register codes.
)
// Register register ecode message map.
func Register(cm map[int]string) {
_messages.Store(cm)
}
// New new a ecode.Codes by int value.
// NOTE: ecode must unique in global, the New will check repeat and then panic.
func New(e int) Code {
if e <= 0 {
panic("business ecode must greater than zero")
}
return add(e)
}
func add(e int) Code {
if _, ok := _codes[e]; ok {
panic(fmt.Sprintf("ecode: %d already exist", e))
}
_codes[e] = struct{}{}
return Int(e)
}
// Codes ecode error interface which has a code & message.
type Codes interface {
// sometimes Error return Code in string form
// NOTE: don't use Error in monitor report even it also work for now
Error() string
// Code get error code.
Code() int
// Message get code message.
Message() string
//Detail get error detail,it may be nil.
Details() []interface{}
// Equal for compatible.
// Deprecated: please use ecode.EqualError.
Equal(error) bool
}
// A Code is an int error code spec.
type Code int
func (e Code) Error() string {
return strconv.FormatInt(int64(e), 10)
}
// Code return error code
func (e Code) Code() int { return int(e) }
// Message return error message
func (e Code) Message() string {
if cm, ok := _messages.Load().(map[int]string); ok {
if msg, ok := cm[e.Code()]; ok {
return msg
}
}
return e.Error()
}
// Details return details.
func (e Code) Details() []interface{} { return nil }
// Equal for compatible.
// Deprecated: please use ecode.EqualError.
func (e Code) Equal(err error) bool { return EqualError(e, err) }
// Int parse code int to error.
func Int(i int) Code { return Code(i) }
// String parse code string to error.
func String(e string) Code {
if e == "" {
return OK
}
// try error string
i, err := strconv.Atoi(e)
if err != nil {
return ServerErr
}
return Code(i)
}
// Cause cause from error to ecode.
func Cause(e error) Codes {
if e == nil {
return OK
}
ec, ok := errors.Cause(e).(Codes)
if ok {
return ec
}
return String(e.Error())
}
// Equal equal a and b by code int.
func Equal(a, b Codes) bool {
if a == nil {
a = OK
}
if b == nil {
b = OK
}
return a.Code() == b.Code()
}
// EqualError equal error
func EqualError(code Codes, err error) bool {
return Cause(err).Code() == code.Code()
}