You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

error.go 2.6 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright (C) MongoDB, Inc. 2017-present.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. package internal
  7. import (
  8. "fmt"
  9. )
  10. // WrappedError represents an error that contains another error.
  11. type WrappedError interface {
  12. // Message gets the basic message of the error.
  13. Message() string
  14. // Inner gets the inner error if one exists.
  15. Inner() error
  16. }
  17. // RolledUpErrorMessage gets a flattened error message.
  18. func RolledUpErrorMessage(err error) string {
  19. if wrappedErr, ok := err.(WrappedError); ok {
  20. inner := wrappedErr.Inner()
  21. if inner != nil {
  22. return fmt.Sprintf("%s: %s", wrappedErr.Message(), RolledUpErrorMessage(inner))
  23. }
  24. return wrappedErr.Message()
  25. }
  26. return err.Error()
  27. }
  28. //UnwrapError attempts to unwrap the error down to its root cause.
  29. func UnwrapError(err error) error {
  30. switch tErr := err.(type) {
  31. case WrappedError:
  32. return UnwrapError(tErr.Inner())
  33. case *multiError:
  34. return UnwrapError(tErr.errors[0])
  35. }
  36. return err
  37. }
  38. // WrapError wraps an error with a message.
  39. func WrapError(inner error, message string) error {
  40. return &wrappedError{message, inner}
  41. }
  42. // WrapErrorf wraps an error with a message.
  43. func WrapErrorf(inner error, format string, args ...interface{}) error {
  44. return &wrappedError{fmt.Sprintf(format, args...), inner}
  45. }
  46. // MultiError combines multiple errors into a single error. If there are no errors,
  47. // nil is returned. If there is 1 error, it is returned. Otherwise, they are combined.
  48. func MultiError(errors ...error) error {
  49. // remove nils from the error list
  50. var nonNils []error
  51. for _, e := range errors {
  52. if e != nil {
  53. nonNils = append(nonNils, e)
  54. }
  55. }
  56. switch len(nonNils) {
  57. case 0:
  58. return nil
  59. case 1:
  60. return nonNils[0]
  61. default:
  62. return &multiError{
  63. message: "multiple errors encountered",
  64. errors: nonNils,
  65. }
  66. }
  67. }
  68. type multiError struct {
  69. message string
  70. errors []error
  71. }
  72. func (e *multiError) Message() string {
  73. return e.message
  74. }
  75. func (e *multiError) Error() string {
  76. result := e.message
  77. for _, e := range e.errors {
  78. result += fmt.Sprintf("\n %s", e)
  79. }
  80. return result
  81. }
  82. func (e *multiError) Errors() []error {
  83. return e.errors
  84. }
  85. type wrappedError struct {
  86. message string
  87. inner error
  88. }
  89. func (e *wrappedError) Message() string {
  90. return e.message
  91. }
  92. func (e *wrappedError) Error() string {
  93. return RolledUpErrorMessage(e)
  94. }
  95. func (e *wrappedError) Inner() error {
  96. return e.inner
  97. }