At the end of quite a long public discussion, the Go team decided to reject the proposal of a built-in try
statement for Go error handling. The decision came ahead of the official Go 2 schedule due to the Go community's negative reaction, writes Robert Griesemer, one of the original designers of the language.
As Google engineer Russ Cox recalled in his response to an open letter about try
, error handling has consistently been one of the top pain points for Go users for a number of years. Consequently, the Go team started working on it with the goal to overhaul error handling in Go 2, as Griesemer explains, but only to find out the overall Go community was not ready for the change:
We have just dedicated quite a bit of time and energy on this over the last half year and especially the last 3 months, and we were quite happy with the proposal, yet we have obviously underestimated the possible reaction towards it. Now it does make a lot of sense to step back, digest and distill the feedback, and then decide on the best next steps.
The reason why Go error handling is considered a pain point by many Go developers is its requirement to explicitly handle errors when calling a function by forcing too much boilerplate on the developer, as you can see in the following example:
value, err := DoSomething()
if err != nil {
log.Println(err)
return err
}
This is considered tedious and in itself error prone, for example for the possibility of inverting the check using if error == nil
, which can lead to subtle errors in code reviews. In addition, the readability of the code is affected even more when developers follow the best practice of decorating errors with some context-local information before returning them back.
All of this led to the now-rejected try
proposal, which, in its final form, introduced a try
statement to wrap calls to functions that may fail and an additional defer
statement to be used to propagate context information:
f := try(os.Open(filename))
...
// err is the name of the error result of the enclosing function
defer func() {
if err != nil { // no error may have occurred - check for it
err = … // wrap/augment error
}
}()
Criticism to this proposal included reducing explicitness of return
points in exchange for less code repetitition; the need to use a named error variable when using defer
; more complex debugging to add debug-only if
statements; and more complex code coverage analysis. An additional concern that was raised highlighted the fact that while it was true that error handling was among the top Go issues in many surveys, this was due to a mere 5% of surveyed developers. All of this made the Go team backtrack on their proposal and leave work on error handling for a later moment:
Google is not stopping work on this and accepts feedback to what parts of error handling are more cumbersome.
On the good side of things, Russ Cox pointed out the community-wide discussion about try
was open source at its best, in spite of the final outcome being a rejection.
If you want, you can leave your feedback to provide the Go team with more detailed and varied opinions on the matter.