ecode.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package ecode
  2. import (
  3. "fmt"
  4. "strconv"
  5. "sync/atomic"
  6. "github.com/pkg/errors"
  7. )
  8. var (
  9. _messages atomic.Value // NOTE: stored map[string]map[int]string
  10. _codes = map[int]struct{}{} // register codes.
  11. )
  12. // Register register ecode message map.
  13. func Register(cm map[int]string) {
  14. _messages.Store(cm)
  15. }
  16. // New new a ecode.Codes by int value.
  17. // NOTE: ecode must unique in global, the New will check repeat and then panic.
  18. func New(e int) Code {
  19. if e <= 0 {
  20. panic("business ecode must greater than zero")
  21. }
  22. return add(e)
  23. }
  24. func add(e int) Code {
  25. if _, ok := _codes[e]; ok {
  26. panic(fmt.Sprintf("ecode: %d already exist", e))
  27. }
  28. _codes[e] = struct{}{}
  29. return Int(e)
  30. }
  31. // Codes ecode error interface which has a code & message.
  32. type Codes interface {
  33. // sometimes Error return Code in string form
  34. // NOTE: don't use Error in monitor report even it also work for now
  35. Error() string
  36. // Code get error code.
  37. Code() int
  38. // Message get code message.
  39. Message() string
  40. //Detail get error detail,it may be nil.
  41. Details() []interface{}
  42. // Equal for compatible.
  43. // Deprecated: please use ecode.EqualError.
  44. Equal(error) bool
  45. }
  46. // A Code is an int error code spec.
  47. type Code int
  48. func (e Code) Error() string {
  49. return strconv.FormatInt(int64(e), 10)
  50. }
  51. // Code return error code
  52. func (e Code) Code() int { return int(e) }
  53. // Message return error message
  54. func (e Code) Message() string {
  55. if cm, ok := _messages.Load().(map[int]string); ok {
  56. if msg, ok := cm[e.Code()]; ok {
  57. return msg
  58. }
  59. }
  60. return e.Error()
  61. }
  62. // Details return details.
  63. func (e Code) Details() []interface{} { return nil }
  64. // Equal for compatible.
  65. // Deprecated: please use ecode.EqualError.
  66. func (e Code) Equal(err error) bool { return EqualError(e, err) }
  67. // Int parse code int to error.
  68. func Int(i int) Code { return Code(i) }
  69. // String parse code string to error.
  70. func String(e string) Code {
  71. if e == "" {
  72. return OK
  73. }
  74. // try error string
  75. i, err := strconv.Atoi(e)
  76. if err != nil {
  77. return ServerErr
  78. }
  79. return Code(i)
  80. }
  81. // Cause cause from error to ecode.
  82. func Cause(e error) Codes {
  83. if e == nil {
  84. return OK
  85. }
  86. ec, ok := errors.Cause(e).(Codes)
  87. if ok {
  88. return ec
  89. }
  90. return String(e.Error())
  91. }
  92. // Equal equal a and b by code int.
  93. func Equal(a, b Codes) bool {
  94. if a == nil {
  95. a = OK
  96. }
  97. if b == nil {
  98. b = OK
  99. }
  100. return a.Code() == b.Code()
  101. }
  102. // EqualError equal error
  103. func EqualError(code Codes, err error) bool {
  104. return Cause(err).Code() == code.Code()
  105. }