-
Notifications
You must be signed in to change notification settings - Fork 17.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: block scoped error handling #33161
Comments
There seems to be a magic variable "err" in the handle block. Where was it defined? |
@urandom that is on purpose. The proposal says:
Another way to do this would define handle blocks as If handle blocks define variables it cold probably be overloaded to handle Edit: Proposal changed to no longer have an implicit |
I proposed this under the name
Some thoughts:
|
@carlmjohnson although this looks similar to
The block should not control the flow of your program. Here are some examples why: Go functions
Loops
If you do not wait for
|
Is fmt.Printf(
"Result: %v\n",
try strconv.ParseInt(term1, 10, 0) handle { return err } + try strconv.ParseInt(term2, 10, 0) handle { return err }),
) legal? I think I prefer this with the explicit variable declaration. It does make it a bit more verbose, but by making it explicit it removes the hidden nature of it and also makes it, as you mentioned, capable of handling other usages such as map retrievals and whatnot. The biggest issue I have with this is that it puts the actual function call so far down into the line, surrounded by what is essentially boilerplate. It's one of the reasons that I prefer separate v, err := strconv.ParseInt(str, 10, 0)
if err != nil {
// ...
} to be a lot more readable, and easier to edit later, than if v, err := strconv.ParseInt(str, 10, 0); err != nil {
// ...
} Might just be my personal preference, though. |
@DeedleFake, yes I would expect Your function would probably look like
|
@DeedleFake to respond to
I haven't put enough thought into the implications, so take this with a bag of salt. If this isn't implemented until Go2 maybe the return from map retrievals and type assertions should change to return an |
I think implicit |
@wdc-python-king, I can understand not wanting more keywords there are already a few I don't use like
|
@mvndaai Explicit err helps. And I'm thinking of a type switch on errors.
The And I've got some rules. I want error handling be more powerful and enable us to write more robust code. |
@wdc-python-king since one of the main goals of changing errors is to reduce boilerplate, being explicit on just
The reason I would be okay with
|
@wdc-python-king it seems like you would prefer a type switch on errors, something this is equivalent to this:
Coming in 1.13, or currently using xerrors, will be
Here is an example of how you could do what you want:
|
@mvndaai Yes. With The Go team solved it without adding any language feature, which I would appreciate. The reason I would be ok with explicit err is to follow the
IMHO, I would just make |
I updated the proposal to make
|
@mvndaai Although I think the Go team is unlikely to revisit error handling anytime soon, I do like your proposal and unless there are side-effects I do not yet see I would be happy to see it included in a future version Go. #fwiw |
Except for the scoping, there's really not much difference between r := try os.Open(src) handle(err error) {
return err
} and the current approach: r, err := os.Open(src)
if err != nil {
return err
} In fact, the It is very easy to come up with new control flow structures for any language - but it is hard to come up with control flow statements that are universally useful and add significant power. This construct does not add power over what we already have, nor is it universally useful. I don't believe we should add two new keywords and a whole new statement for something we can already write in Go. |
@griesemer that is very fair to say that the only thing gained by this is the scoping of the error, but that was kind of the point. I consider an |
@mvndaai The point you are making about In other words, the mechanism you are introducing would be far more interesting if it could be used in a variety of scenarios, and if it "just happens" to also work well for errors; especially if the mechanism would also be dead simple. Such a mechanism would amortize the cost and complexity it adds to the language by being more universally useful. That more universal construct seems to be a plain |
@griesemer the
Meaning that you could handle a bool or any other type. The main issue with the
Thinking about this more, a |
@mvndaai Exactly. That's also the reason why |
For the reasons given above in #33161 (comment) and subsequent discussion, this is a likely decline. Leaving open for four week for final comments. |
No final comments. Closing. |
After reading through the problem overview the try() proposal and every comment on the try() issue #32437 I like the idea of try(), thank you everyone for such hard work! The implementations so far have not solved what I view as the issue of error boilerplate, namely the scope of the
err
var.Problem
Go scopes errors using inline
if
statements, but does not scope errors when a variable needs to be used after.Scoped:
Not Scoped:
When the error is not scoped it is has multiple problems. The ones that come to mind are:
err
s need to be the same typeProposal
I propose the language add
try
/handle
keywords similar to what was proposed by @james-lawrence.The
try
keyword would return everything but the final value. Thehandle
block would only run if the final value was non-zero.This proposal also solves many common complaints from the
try
proposal #32437:return
Examples
CopyFile
The
CopyFile
func found in the overview becomesThe main difference between current error boilerplate and using block scoped error handling are:
err
fromos.Open(src)
doesn't live for the whole scope of the functiondefer
functions can handle their errors in the same manner as other functionsHex
The
hex
example in the overview becomes:This is very similar to the current go except the
err
returned fromioutil.ReadAll
isn't overwritten by theerr
fromparseHexdump
.Inline/Curried functions
The
try
proposal comments included examples of nested/curried functions that caused some worry such as thisAsCommit
.Wrapping a
try
/handle
in()
would mean a variable never needs to be saved if it is not wanted. This case is similar to using an anonymous funcfunc()int { ... }()
and handling the error, but would allow use of other keywords likebreak
,continue
, andreturn
.Current Go
With block scoped error handling (please don't do this)
Struct Init
Current go
With block scoped error handling
The text was updated successfully, but these errors were encountered: