wrap.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package xerrors
  5. import (
  6. "reflect"
  7. )
  8. // A Wrapper provides context around another error.
  9. type Wrapper interface {
  10. // Unwrap returns the next error in the error chain.
  11. // If there is no next error, Unwrap returns nil.
  12. Unwrap() error
  13. }
  14. // Opaque returns an error with the same error formatting as err
  15. // but that does not match err and cannot be unwrapped.
  16. func Opaque(err error) error {
  17. return noWrapper{err}
  18. }
  19. type noWrapper struct {
  20. error
  21. }
  22. func (e noWrapper) FormatError(p Printer) (next error) {
  23. if f, ok := e.error.(Formatter); ok {
  24. return f.FormatError(p)
  25. }
  26. p.Print(e.error)
  27. return nil
  28. }
  29. // Unwrap returns the result of calling the Unwrap method on err, if err implements
  30. // Unwrap. Otherwise, Unwrap returns nil.
  31. //
  32. // Deprecated: As of Go 1.13, use errors.Unwrap instead.
  33. func Unwrap(err error) error {
  34. u, ok := err.(Wrapper)
  35. if !ok {
  36. return nil
  37. }
  38. return u.Unwrap()
  39. }
  40. // Is reports whether any error in err's chain matches target.
  41. //
  42. // An error is considered to match a target if it is equal to that target or if
  43. // it implements a method Is(error) bool such that Is(target) returns true.
  44. //
  45. // Deprecated: As of Go 1.13, use errors.Is instead.
  46. func Is(err, target error) bool {
  47. if target == nil {
  48. return err == target
  49. }
  50. isComparable := reflect.TypeOf(target).Comparable()
  51. for {
  52. if isComparable && err == target {
  53. return true
  54. }
  55. if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
  56. return true
  57. }
  58. // TODO: consider supporing target.Is(err). This would allow
  59. // user-definable predicates, but also may allow for coping with sloppy
  60. // APIs, thereby making it easier to get away with them.
  61. if err = Unwrap(err); err == nil {
  62. return false
  63. }
  64. }
  65. }
  66. // As finds the first error in err's chain that matches the type to which target
  67. // points, and if so, sets the target to its value and returns true. An error
  68. // matches a type if it is assignable to the target type, or if it has a method
  69. // As(interface{}) bool such that As(target) returns true. As will panic if target
  70. // is not a non-nil pointer to a type which implements error or is of interface type.
  71. //
  72. // The As method should set the target to its value and return true if err
  73. // matches the type to which target points.
  74. //
  75. // Deprecated: As of Go 1.13, use errors.As instead.
  76. func As(err error, target interface{}) bool {
  77. if target == nil {
  78. panic("errors: target cannot be nil")
  79. }
  80. val := reflect.ValueOf(target)
  81. typ := val.Type()
  82. if typ.Kind() != reflect.Ptr || val.IsNil() {
  83. panic("errors: target must be a non-nil pointer")
  84. }
  85. if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) {
  86. panic("errors: *target must be interface or implement error")
  87. }
  88. targetType := typ.Elem()
  89. for err != nil {
  90. if reflect.TypeOf(err).AssignableTo(targetType) {
  91. val.Elem().Set(reflect.ValueOf(err))
  92. return true
  93. }
  94. if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
  95. return true
  96. }
  97. err = Unwrap(err)
  98. }
  99. return false
  100. }
  101. var errorType = reflect.TypeOf((*error)(nil)).Elem()