Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatically filtering errors in Go

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?

like image 846
Matt Joiner Avatar asked Oct 31 '22 22:10

Matt Joiner


1 Answers

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.

like image 91
twotwotwo Avatar answered Nov 11 '22 01:11

twotwotwo