Proposal Details

Problem The code looks redundant and cumbersome in cases when you need to check an error match several times. Example:

func foo() {
  err := bar()
  if errors.Is(err, err1) || errors.Is(err, err2) || errors.Is(err, err3) {
    // some logic
  }
}

Solution A new function that will allow you to check for errors like this:

func foo() {
  err := bar()
  if errors.In(err, err1, err2, err3) {
    // some logic
  }
}

Implementation

package errors

func In(err error, target ...error) bool {
  for _, v := range target {
    if errors.Is(err, v) {
      return true
    }
  }

  return false
}

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: seankhliao

I don't think it's a very common thing to do: https://github.com/search?q=language%3AGo+%2F%28errors.Is.*%5C%7C%5C%7C%29%2B%2F&type=code

Comment From: zigo101

How about

// Match returns the matched error in targets for err.
func Match(err error, targets ...error) error 

?

Comment From: mauri870

Besides the if condition with multiple errors.Is it is also common to have a slice of errors that you want to match against, for example

var persistentErrors := []error{...}

func isPersistentError(err error) bool {
    for _, e := range persistentErrors {
        if errors.Is(err, e) {
            return true
        }
    }

    return false
}

This would simply turn into a single line with this proposal.

https://github.com/search?q=language%3AGo+%2Ffor+.%3F%2C+.%3F+%3A%3D+range+.+%5C%7B%5Csif+errors%5C.Is%5C%28.%3F%2C+.%3F%5C%29+%5C%7B%2F&type=code

Comment From: seankhliao

I don't think that would be correct. Is unwraps the err to recursively match against target, but if you flip it (the only way for 1 to match against many), it would try to unwrap the target error and only check against the top level of errors.

Comment From: maranqz

I don't think it's a very common thing to do: https://github.com/search?q=language%3AGo+%2F%28errors.Is.*%5C%7C%5C%7C%29%2B%2F&type=code

I would be add also this search query, which shows that people implement this feature for themselves.

Comment From: jimmyfrasche

The implementation in the first post is inefficient as it could be checking each node in the error tree against all candidates in a single sweep instead of n.

There's also a more interesting variation where you can return the sentinel which matches or nil if none do. You can use that in a switch statement, in addition to using it with != nil to get the In() behavior. edit: I see @zigo101 proposed that signature above.