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
- proposal: errors: add Errors as a standard way to represent multiple errors as a single error #47811 (closed)
- proposal: errors: add Errors function to undo Join #57358 (closed)
- proposal: errors: add error matching utility functions #65121 (closed)
- [Feature Request] Shorter error catching #18425 (closed)
- proposal: errors: add NewJoinedErrors #48831 (closed)
(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.