-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecode.go
137 lines (118 loc) · 2.68 KB
/
ecode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package ecode
import (
"fmt"
"strconv"
"sync/atomic"
"github.com/pkg/errors"
)
// init normal ecode
var (
OK = add(0, "success") // ok
ServerErr = New(10000, "server error")
)
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, m string) Code {
if e <= 0 {
panic("business ecode must greater than zero")
}
return add(e, m)
}
func add(e int, m string) Code {
if _, ok := _codes[e]; ok {
panic(fmt.Sprintf("ecode: %d already exist", e))
}
_codes[e] = struct{}{}
if cm, ok := _messages.Load().(map[int]string); ok {
cm[e] = m
Register(cm)
} else {
cm := make(map[int]string, 0)
cm[e] = m
Register(cm)
}
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 e.Message()
}
// 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()
}