Is determines whether one of the causes of the given error or any of its causes is equivalent to some reference error. As in the Go standard library, an error is considered to match a reference error if it is equal to that target or if it implements a method Is(error) bool such that Is(reference) r
(err, reference error)
| 42 | // package location or a different type, ensure that |
| 43 | // RegisterTypeMigration() was called prior to Is(). |
| 44 | func Is(err, reference error) bool { |
| 45 | if reference == nil { |
| 46 | return err == nil |
| 47 | } |
| 48 | |
| 49 | isComparable := reflect.TypeOf(reference).Comparable() |
| 50 | |
| 51 | // Direct reference comparison is the fastest, and most |
| 52 | // likely to be true, so do this first. |
| 53 | for c := err; c != nil; c = errbase.UnwrapOnce(c) { |
| 54 | if isComparable && c == reference { |
| 55 | return true |
| 56 | } |
| 57 | // Compatibility with std go errors: if the error object itself |
| 58 | // implements Is(), try to use that. |
| 59 | if tryDelegateToIsMethod(c, reference) { |
| 60 | return true |
| 61 | } |
| 62 | |
| 63 | // Recursively try multi-error causes, if applicable. |
| 64 | for _, me := range errbase.UnwrapMulti(c) { |
| 65 | if Is(me, reference) { |
| 66 | return true |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | for errNext := err; errNext != nil; errNext = errbase.UnwrapOnce(errNext) { |
| 72 | if isMarkEqual(errNext, reference) { |
| 73 | return true |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | return false |
| 78 | } |
| 79 | |
| 80 | func isMarkEqual(err, reference error) bool { |
| 81 | _, errIsMark := err.(*withMark) |