Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: errors: Has function #64771

Closed
neilotoole opened this issue Dec 17, 2023 · 3 comments
Closed

proposal: errors: Has function #64771

neilotoole opened this issue Dec 17, 2023 · 3 comments
Labels
Milestone

Comments

@neilotoole
Copy link

neilotoole commented Dec 17, 2023

Proposal

Add a tiny errors.Has function to make the errors.As mechanism ergonomically available in if statements.

errors.As is an essential function in the error-wrapping world we live in. But sometimes the caller is only interested in the type of the target, not its value. In that situation, errors.As is awkward to use in conditionals.

Implementation

Add a function errors.Has:

// Has returns true if err, or an error in its error tree, matches error type E.
// An error is considered a match by the rules of [errors.As].
func Has[E error](err error) bool {
  return errors.As(err, new(E))
}

A quick GH search reveals many candidate usages. Here's one example:

  err = container.RunExec(ctx, s.dockerCli, target.ID, exec)
  var sterr cli.StatusError
  if errors.As(err, &sterr) {
    return sterr.StatusCode, nil
  }
  return 0, err

This could be rewritten to:

  err = container.RunExec(ctx, s.dockerCli, target.ID, exec)
  if errors.Has[*cli.StatusError](err) {
    return sterr.StatusCode, nil
  }
  return 0, err

For

  • It's a trivial addition, and makes it explicit that you're only interested in the type, not the value, so it adds to the clarity of the code.
  • The errors.As(err, new(E)) construct obviously isn't widely known; errors.Has is discoverable.

Against

  • We could instead just document the errors.As(err, new(E)) construct in the errors.As documentation.

Naming

Obviously errors.Has is similar to errors.As. Maybe that'll cause confusion? Although, it didn't stop errors.As and errors.Is.

That said, a name like errors.HasType is more explicit. But I absolutely hate it in comparison to errors.Has. I think the "typey" intent of the function is already made obvious by the type parameter. And when I see As, Is and Has together, is it not the missing triplet separated at birth?

@gopherbot gopherbot added this to the Proposal milestone Dec 17, 2023
@neilotoole neilotoole changed the title proposal: errors: Has() function proposal: errors: Has function Dec 17, 2023
@seankhliao
Copy link
Member

see also #51945

@seankhliao
Copy link
Member

seankhliao commented Dec 17, 2023

your search only shows usages of errors.As, not specifically that the value of the error wasn't used
most seem to use !errors.As to early return from when they can't provide more detail, but do make use of the error details further on.

@neilotoole
Copy link
Author

@seankhliao: Ah, somehow I missed #51945. Obvious duplicate. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants