Go's proposed try() will be used and that will change how code is written

July 16, 2019

One of the recent commotions in Go is over the Go team's proposed try() built-in error check function, which is currently planned to be part of Go 1.14 (cf). To simplify, 'a, [...] := try(f(...))' can be used to replace what you would today have to write as:

a, [...], err := f(...)
if err != nil {
   return [...], err
}

Using try() means you can drop that standard if block and makes your function clearer; much more of the code that remains is relevant and important.

Try() is attractive and will definitely be used in Go code, probably widely, and especially by people who are new to Go and writing more casual code. However, this widespread use of try() is going to change how Go code is written.

One of my firm beliefs is that most programmers are strongly driven to do what their languages make easy, and I don't think try() is any exception (I had similar thoughts about the original error handling proposal). What try() does is that try() makes returning an unchanged error the easiest thing to do. You can wrap the error from f() with more context if you work harder, but the easiest path is to not wrap it at all. This is a significant change from the current state of Go, where wrapping an error is a very easy thing that needs almost no change to the boilerplate code:

a, [...], err := f(...)
if err != nil {
   return [...], fmt.Errorf("....", ..., err)
}

In a try() world, adding that error wrapping means adding those three lines of near boilerplate back in. As a result, I think that once try() is introduced, Go code will see a significantly increased use of errors being returned unchanged and unwrapped from deep in the call stack. Sure, it's not perfect, but programmers are very good at convincing themselves that it's good enough. I'm sure that I'll do it myself.

This change isn't necessarily bad by itself, but it does directly push against the Go team's efforts to put more context into error values, an effort that actually landed changes in the forthcoming Go 1.13 (see also the draft design). It's possible to combine try() and better errors in clever ways, as shown by How to use 'try', but it's not the obvious, easy path, and I don't think it's going to be a common way to use try().

I am neither for or against try() at the moment, because I think that being for or against it in isolation is asking the wrong question. The important question is how Go wants errors to work, and right now the Go team does not seem to have made up its mind. If the Go team decides that errors should frequently be wrapped on their way up the call stack, I believe that try() in its current form is a bad idea.

(If the Go team thinks that they can have both try() in its current form and people routinely wrapping errors, I think that they are fooling themselves. try() will be used in the easiest way to use it, because that's what people do.)

PS: While Go culture is currently relatively in favour of wrapping errors with additional information, I don't think that this culture will survive the temptation of try(). You can't persuade people to regularly do things the hard way for very long.

Update: The Go team dropped the try() proposal due to community objections, rendering the issue moot.


Comments on this page:

I find it comical that you posted this the same day they officially gave up on `try()`

By cks at 2019-07-17 08:28:45:

That'll sort of teach me to sit on entry ideas while I think about them. I actually started writing this as Monday's entry but it wasn't coming together then (and I've been thinking about the issue for a while, of course).

I'm actually surprised that the Go team gave up on try(). They seemed so definitive and dismissive of the community feedback that they'd received in the issue and their blog post that I figured this was going to be a case where the community got steamrollered, like modules. As peculiar as it sounds, I'm not sure how I feel about this, since any change in error handling is probably going to be controversial.

(I'm pretty sure that any meaningful change in error handling will significantly change how Go code is written, and implicitly change the feel of the language in clearly visible ways. Current users almost always object to the latter, especially people who are strongly committed to the language and who have thus made their peace with the current way.)

Written on 16 July 2019.
« ZFS on Linux still has annoying issues with ARC size
Django 1.11 has a bug that causes intermittent CSRF validation failures »

Page tools: View Source, View Normal.
Search:
Login: Password:

Last modified: Tue Jul 16 23:36:22 2019
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.