package ecode import ( "fmt" "strconv" "sync/atomic" "github.com/pkg/errors" ) var ( _messages atomic.Value // NOTE: stored 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{} } // 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 } // 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() }