5

The error type in Go is quite broad, and the actual type contained can vary by platform as well as between versions. Is it idiomatic to filter errors that we expect by the error's string value, error.Error()?

For example:

_, err := conn.Write(b)
if err != nil {
    if !strings.Contains(err.Error(), "peer reset") {
        log.Print(err)
    }
    return
}

Is there a better way to do this?

2
  • Poking around in the string representation of error is fragile at best and not a good idea. I wrote an answer to another question that goes over the ways a package author can make errors that are testable by consumers. If you need to test for or handle errors that don't use one of those easy methods then you've found a flaw in that package and should report it as an issue. I'd go so far as fixing it in a fork before I'd muck around with the error string. Commented Aug 2, 2015 at 14:26
  • Your new "stringly-typed" SO tag makes no sense to me; I'd recommend removing it. Commented Aug 3, 2015 at 19:12

2 Answers 2

3

I'm not sure I'm saying anything you don't know, but I've seen a few ways to handle it: compare to known instances when they are exported and appear in the godoc, like io.EOF or os.ErrNotExist; using type assertions or switches when the docs promise an error of a certain type, like *os.PathError or *os.LinkError; or giving up and looking at messages. The first should be clear enough and you've done the third in your question; checking for type could look like:

if pathErr, ok := err.(*os.PathError); ok {
    log.Fatal("Bad path " + pathErr.Path + ", giving up")
} else if err != nil {
    return err
}

I think this would be rare, but if you had several potential types involved, you could conceivably use a type switch:

switch err.(type) {
case *os.PathError, *os.LinkError:
    log.Fatal("oof")
case nil:
    // nothing; prevents default
default:
    log.Fatal("huh")
}

(The choice of error and behavior here is a bit silly--I'm just trying to put up a template with the syntax.)

The hard part you allude to in your question: it may not be clear what guarantees you have about what errors will be returned. I know that, for example, the 1.5 release notes say that they're standardizing more on net.OpError for net errors than before, but that's all I know. Spelunking in the source of the package you're calling, or asking people questions, may be in order if there are important cases you think are unclear.

Sign up to request clarification or add additional context in comments.

3 Comments

You've summed up pretty much where I'm currently at.
Your example is net errors; wonder if it's worth asking golang-nuts about adding a (*net.OpError).Type() where Type is one of a set of known error values (imagine,net.ErrConnReset, net.ErrAddrInUse, etc.)--or to standardize opError.Error(), or to document if some things are in fact reliable but not documented.
(If not Type(), maybe a Code() or Errno() using POSIX error codes.)
0

errors.Is and errors.As added in more recent versions of Go would now address this problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.