/vendor/github.com/kataras/iris/core/errors/errors.go

https://github.com/jdcloud-bds/bds · Go · 168 lines · 108 code · 25 blank · 35 comment · 20 complexity · 92a8c9a9fa47d0acd7e8a58f4ce32157 MD5 · raw file

  1. package errors
  2. import (
  3. "fmt"
  4. "runtime"
  5. "strings"
  6. "github.com/iris-contrib/go.uuid"
  7. )
  8. var (
  9. // Prefix the error prefix, applies to each error's message.
  10. Prefix = ""
  11. )
  12. // Error holds the error message, this message never really changes
  13. type Error struct {
  14. // ID returns the unique id of the error, it's needed
  15. // when we want to check if a specific error returned
  16. // but the `Error() string` value is not the same because the error may be dynamic
  17. // by a `Format` call.
  18. ID string `json:"id"`
  19. // The message of the error.
  20. Message string `json:"message"`
  21. // Apennded is true whenever it's a child error.
  22. Appended bool `json:"appended"`
  23. // Stack returns the list of the errors that are shown at `Error() string`.
  24. Stack []Error `json:"stack"` // filled on AppendX.
  25. }
  26. // New creates and returns an Error with a pre-defined user output message
  27. // all methods below that doesn't accept a pointer receiver because actually they are not changing the original message
  28. func New(errMsg string) Error {
  29. uidv4, _ := uuid.NewV4() // skip error.
  30. return Error{
  31. ID: uidv4.String(),
  32. Message: Prefix + errMsg,
  33. }
  34. }
  35. // NewFromErr same as `New` but pointer for nil checks without the need of the `Return()` function.
  36. func NewFromErr(err error) *Error {
  37. if err == nil {
  38. return nil
  39. }
  40. errp := New(err.Error())
  41. return &errp
  42. }
  43. // Equal returns true if "e" and "to" are matched, by their IDs if it's a core/errors type otherwise it tries to match their error messages.
  44. // It will always returns true if the "to" is a children of "e"
  45. // or the error messages are exactly the same, otherwise false.
  46. func (e Error) Equal(to error) bool {
  47. if e2, ok := to.(Error); ok {
  48. return e.ID == e2.ID
  49. } else if e2, ok := to.(*Error); ok {
  50. return e.ID == e2.ID
  51. }
  52. return e.Error() == to.Error()
  53. }
  54. // Empty returns true if the "e" Error has no message on its stack.
  55. func (e Error) Empty() bool {
  56. return e.Message == ""
  57. }
  58. // NotEmpty returns true if the "e" Error has got a non-empty message on its stack.
  59. func (e Error) NotEmpty() bool {
  60. return !e.Empty()
  61. }
  62. // String returns the error message
  63. func (e Error) String() string {
  64. return e.Message
  65. }
  66. // Error returns the message of the actual error
  67. // implements the error
  68. func (e Error) Error() string {
  69. return e.String()
  70. }
  71. // Format returns a formatted new error based on the arguments
  72. // it does NOT change the original error's message
  73. func (e Error) Format(a ...interface{}) Error {
  74. e.Message = fmt.Sprintf(e.Message, a...)
  75. return e
  76. }
  77. func omitNewLine(message string) string {
  78. if strings.HasSuffix(message, "\n") {
  79. return message[0 : len(message)-2]
  80. } else if strings.HasSuffix(message, "\\n") {
  81. return message[0 : len(message)-3]
  82. }
  83. return message
  84. }
  85. // AppendInline appends an error to the stack.
  86. // It doesn't try to append a new line if needed.
  87. func (e Error) AppendInline(format string, a ...interface{}) Error {
  88. msg := fmt.Sprintf(format, a...)
  89. e.Message += msg
  90. e.Appended = true
  91. e.Stack = append(e.Stack, New(omitNewLine(msg)))
  92. return e
  93. }
  94. // Append adds a message to the predefined error message and returns a new error
  95. // it does NOT change the original error's message
  96. func (e Error) Append(format string, a ...interface{}) Error {
  97. // if new line is false then append this error but first
  98. // we need to add a new line to the first, if it was true then it has the newline already.
  99. if e.Message != "" {
  100. e.Message += "\n"
  101. }
  102. return e.AppendInline(format, a...)
  103. }
  104. // AppendErr adds an error's message to the predefined error message and returns a new error.
  105. // it does NOT change the original error's message
  106. func (e Error) AppendErr(err error) Error {
  107. return e.Append(err.Error())
  108. }
  109. // HasStack returns true if the Error instance is created using Append/AppendInline/AppendErr funcs.
  110. func (e Error) HasStack() bool {
  111. return len(e.Stack) > 0
  112. }
  113. // With does the same thing as Format but it receives an error type which if it's nil it returns a nil error.
  114. func (e Error) With(err error) error {
  115. if err == nil {
  116. return nil
  117. }
  118. return e.Format(err.Error())
  119. }
  120. // Ignore will ignore the "err" and return nil.
  121. func (e Error) Ignore(err error) error {
  122. if err == nil {
  123. return e
  124. }
  125. if e.Error() == err.Error() {
  126. return nil
  127. }
  128. return e
  129. }
  130. // Panic output the message and after panics.
  131. func (e Error) Panic() {
  132. _, fn, line, _ := runtime.Caller(1)
  133. errMsg := e.Message
  134. errMsg += "\nCaller was: " + fmt.Sprintf("%s:%d", fn, line)
  135. panic(errMsg)
  136. }
  137. // Panicf output the formatted message and after panics.
  138. func (e Error) Panicf(args ...interface{}) {
  139. _, fn, line, _ := runtime.Caller(1)
  140. errMsg := e.Format(args...).Error()
  141. errMsg += "\nCaller was: " + fmt.Sprintf("%s:%d", fn, line)
  142. panic(errMsg)
  143. }