coder.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package errors
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. type Coder interface {
  7. // HTTPStatus 返回http状态码
  8. HTTPStatus() int
  9. // String 展示给外部用户的错误信息
  10. String() string
  11. // Reference 展示给用户解决错误需要参开的引用文档
  12. Reference() string
  13. // Code 错误码
  14. Code() int
  15. }
  16. // 错误码映射
  17. var codes = map[int]Coder{}
  18. var codeMux = &sync.Mutex{}
  19. // Register 注册错误码,存在会被覆盖
  20. func Register(coder Coder) {
  21. if coder.Code() == 999999 {
  22. panic("code `999999` is reserved by system as unknownCode error code")
  23. }
  24. codeMux.Lock()
  25. defer codeMux.Unlock()
  26. codes[coder.Code()] = coder
  27. }
  28. // MustRegister 注册错误码,已注册报错
  29. func MustRegister(coder Coder) {
  30. if coder.Code() == 999999 {
  31. panic("code `999999` is reserved by system as unknownCode error code")
  32. }
  33. codeMux.Lock()
  34. defer codeMux.Unlock()
  35. if _, ok := codes[coder.Code()]; ok {
  36. panic(fmt.Sprintf("code: %d already exist", coder.Code()))
  37. }
  38. codes[coder.Code()] = coder
  39. }
  40. // ParseCoder 解析错误码
  41. // 将错误解析为 *withCode 类型。如果原生错误不是本错误包生成,返回未知错误
  42. func ParseCoder(err error) Coder {
  43. if err == nil {
  44. return nil
  45. }
  46. if v, ok := err.(*withCode); ok {
  47. if coder, ok := codes[v.code]; ok {
  48. return coder
  49. }
  50. }
  51. return unknownCoder
  52. }
  53. // IsCode 判断错误码是否在当前错误链中
  54. func IsCode(err error, code int) bool {
  55. if v, ok := err.(*withCode); ok {
  56. if v.code == code {
  57. return true
  58. }
  59. if v.cause != nil {
  60. return IsCode(v.cause, code)
  61. }
  62. return false
  63. }
  64. return false
  65. }