error handling: Which errors to ignore?

407 views
Skip to first unread message

Torsten Bronger

unread,
Feb 6, 2016, 1:35:37 PM2/6/16
to golan...@googlegroups.com
Hallöchen!

Coming from Python, I'm used to the mantra "errors should never pass
silently". However, this seems to be a bad idea in Go if you don't
want to end up with something like this:

if _, err := fmt.Printf("Hello!"); err != nil {
log.Fatalln(err)
}

I've read much online about best practices in Go error handling, but
no source answered the question which errors to ignore. Is it
correct that there are no publications on this topic and every
Gopher must find a rule set on their own?

It still feels wrong to ignore errors in the first place, though ...

Tschö,
Torsten.

--
Torsten Bronger Jabber ID: torsten...@jabber.rwth-aachen.de

Tamás Gulácsi

unread,
Feb 6, 2016, 2:39:37 PM2/6/16
to golang-nuts
1. Check every error, esp. for precious data. For example don't ignore the Close's error after writing...
2. Only ignore error when you know that's the good way
3. Use github.com/kisielk/errcheck

Niko Schwarz

unread,
Feb 7, 2016, 4:15:08 PM2/7/16
to golang-nuts, bro...@physik.rwth-aachen.de
The guidance around this is so vague because, ultimately, error handling depends on what you want your program to achieve.

For example, if a banking system failed to write a monetary transaction into some log, perhaps because of a network error, I'd expect there to be rather thorough logic on how to make sure that everything ends in a valid state. But what is that state? Should the transaction be written somewhere else, so it can be resumed later? Should the transaction be aborted altogether? Perhaps the right answer is a sub-component that triggers a red lamp in the CEO's office to blink, so that he hurls down into the server room and start writing apology letters from there. 

But that isn't a Go question. It's a question of what the correct behavior of your program is. 

Niko

Torsten Bronger

unread,
Feb 7, 2016, 5:01:53 PM2/7/16
to golan...@googlegroups.com
Hallöchen!

Niko Schwarz writes:

> [...]
>
> But that isn't a Go question. It's a question of what the correct
> behavior of your program is.

This is true, but this question arises especially in Go (and some
other languages) because there is no implicit "abort on error", or a
simple way to activate such. Thus, you have to make a compromise
between ignoring errors and cluttering the code.

Dave Cheney

unread,
Feb 7, 2016, 5:51:26 PM2/7/16
to golang-nuts, bro...@physik.rwth-aachen.de
My rule of thumb is -- you only need to check the error if you care about the result of the function. For example

    x, err := fn()

If you want to use the value of x, you must first check the error. The example you provided, IMO, is an exception to almost all the rules, and shouldn't be used as a basis for forming a general strategy around error handling. To explain what I mean, 

fmt.Sprint{f,ln} does not return an error

fmt.Fprint{f,ln} takes an io.Writer to write to, you should check the error there -- if you care about the write succeeding. Alternatively you might defer error checking til the end of you use of the writer, as most underlying writers will return a persistent error when w.Close() is called. ie, if a write to the writer failed, the close will also return some kind of error, also noting that most writers do not flush their data to disk until they are closed. You may also be using a wrapper like the one Rob described here, https://blog.golang.org/errors-are-values, to enforce the behaviour described above.
  
fmt.Printf is the exception, because it is a convenience method around fmt.Fprintf(os.Stdout). Most code skips the error checking there because, a, it's unusual for stdout to be closed, b. if it is closed, what are you going to do about it. Ignoring the error checking here falls back on the logic of "you only need to check the error if you care about the result of the function" -- in not checking that a write to stdout succeeded the authors of that code are saying explicitly that they don't care if it worked or not, which in general seems to be the right trade off.

Thanks

Dave

Torsten Bronger

unread,
Feb 7, 2016, 6:51:30 PM2/7/16
to golan...@googlegroups.com
Hallöchen!

Tamás Gulácsi writes:

> [...]
>
> 3. Use github.com/kisielk/errcheck

Thank you, this looks interesting!

Torsten Bronger

unread,
Feb 7, 2016, 6:55:23 PM2/7/16
to golan...@googlegroups.com
Hallöchen!

Dave Cheney writes:

> My rule of thumb is -- you only need to check the error if you care about
> the result of the function. For example
>
> x, err := fn()

Really only care about "x" or also any other side effect?

> [...] You may also be using a wrapper like the one Rob described
> here, https://blog.golang.org/errors-are-values, to enforce the
> behaviour described above.

Oh, this is a very interesting link, thank you! I don't know how
this could evaded my research.

Dave Cheney

unread,
Feb 7, 2016, 7:33:09 PM2/7/16
to golang-nuts, bro...@physik.rwth-aachen.de


On Monday, 8 February 2016 10:55:23 UTC+11, Torsten Bronger wrote:
Hallöchen!

Dave Cheney writes:

> My rule of thumb is -- you only need to check the error if you care about
> the result of the function. For example
>
>     x, err := fn()

Really only care about "x" or also any other side effect?

The value of x is unknown until you check the error. If the error is not nil, then the value of x cannot be assumed to be anything and must not be used. There is of course an exception to this rule, io.Reader.Read.
Reply all
Reply to author
Forward
0 new messages