Proposal: A built-in Go error check function, try
This proposal has been closed. Thanks, everybody, for your input.
Before commenting, please read the detailed design doc and see the discussion summary as of June 6, the summary as of June 10, and most importantly the advice on staying focussed. Your question or suggestion may have already been answered or made. Thanks.
We propose a new built-in function called try, designed specifically to eliminate the boilerplate if statements typically associated with error handling in Go. No other language changes are suggested. We advocate using the existing defer statement and standard library functions to help with augmenting or wrapping of errors. This minimal approach addresses most common scenarios while adding very little complexity to the language. The try built-in is easy to explain, straightforward to implement, orthogonal to other language constructs, and fully backward-compatible. It also leaves open a path to extending the mechanism, should we wish to do so in the future.
[The text below has been edited to reflect the design doc more accurately.]
The try built-in function takes a single expression as argument. The expression must evaluate to n+1 values (where n may be zero) where the last value must be of type error. It returns the first n values (if any) if the (final) error argument is nil, otherwise it returns from the enclosing function with that error. For instance, code such as
f, err := os.Open(filename)
if err != nil {
return …, err // zero values for other results, if any
}
can be simplified to
f := try(os.Open(filename))
try can only be used in a function which itself returns an error result, and that result must be the last result parameter of the enclosing function.
This proposal reduces the original draft design presented at last year's GopherCon to its essence. If error augmentation or wrapping is desired there are two approaches: Stick with the tried-and-true if statement, or, alternatively, “declare” an error handler with a defer statement:
defer func() {
if err != nil { // no error may have occurred - check for it
err = … // wrap/augment error
}
}()
Here, err is the name of the error result of the enclosing function. In practice, suitable helper functions will reduce the declaration of an error handler to a one-liner. For instance
defer fmt.HandleErrorf(&err, "copy %s %s", src, dst)
(where fmt.HandleErrorf decorates *err) reads well and can be implemented without the need for new language features.
The main drawback of this approach is that the error result parameter needs to be named, possibly leading to less pretty APIs. Ultimately this is a matter of style, and we believe we will adapt to expecting the new style, much as we adapted to not having semicolons.
In summary, try may seem unusual at first, but it is simply syntactic sugar tailor-made for one specific task, error handling with less boilerplate, and to handle that task well enough. As such it fits nicely into the philosophy of Go. try is not designed to address all error handling situations; it is designed to handle the most common case well, to keep the design simple and clear.
Credits
This proposal is strongly influenced by the feedback we have received so far. Specifically, it borrows ideas from:
Detailed design doc
https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md
tryhard tool for exploring impact of try
https://github.com/griesemer/tryhard
Proposal: A built-in Go error check function,
tryThis proposal has been closed. Thanks, everybody, for your input.
Before commenting, please read the detailed design doc and see the discussion summary as of June 6, the summary as of June 10, and most importantly the advice on staying focussed. Your question or suggestion may have already been answered or made. Thanks.
We propose a new built-in function called
try, designed specifically to eliminate the boilerplateifstatements typically associated with error handling in Go. No other language changes are suggested. We advocate using the existingdeferstatement and standard library functions to help with augmenting or wrapping of errors. This minimal approach addresses most common scenarios while adding very little complexity to the language. Thetrybuilt-in is easy to explain, straightforward to implement, orthogonal to other language constructs, and fully backward-compatible. It also leaves open a path to extending the mechanism, should we wish to do so in the future.[The text below has been edited to reflect the design doc more accurately.]
The
trybuilt-in function takes a single expression as argument. The expression must evaluate to n+1 values (where n may be zero) where the last value must be of typeerror. It returns the first n values (if any) if the (final) error argument is nil, otherwise it returns from the enclosing function with that error. For instance, code such ascan be simplified to
trycan only be used in a function which itself returns anerrorresult, and that result must be the last result parameter of the enclosing function.This proposal reduces the original draft design presented at last year's GopherCon to its essence. If error augmentation or wrapping is desired there are two approaches: Stick with the tried-and-true
ifstatement, or, alternatively, “declare” an error handler with adeferstatement:Here,
erris the name of the error result of the enclosing function. In practice, suitable helper functions will reduce the declaration of an error handler to a one-liner. For instance(where
fmt.HandleErrorfdecorates*err) reads well and can be implemented without the need for new language features.The main drawback of this approach is that the error result parameter needs to be named, possibly leading to less pretty APIs. Ultimately this is a matter of style, and we believe we will adapt to expecting the new style, much as we adapted to not having semicolons.
In summary,
trymay seem unusual at first, but it is simply syntactic sugar tailor-made for one specific task, error handling with less boilerplate, and to handle that task well enough. As such it fits nicely into the philosophy of Go.tryis not designed to address all error handling situations; it is designed to handle the most common case well, to keep the design simple and clear.Credits
This proposal is strongly influenced by the feedback we have received so far. Specifically, it borrows ideas from:
Detailed design doc
https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md
tryhardtool for exploring impact oftryhttps://github.com/griesemer/tryhard