-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: aggregate error handling #34140
Comments
It's not that simple though. The specification of "goto" clearly forbids jumping over variable definitions. In the above code, cellVal is defined after preceding "goto fail", so this, as it is, won't work, at least in the current rules of the language. To make it work, we can either manually make sure that all the variables are defined beforehand, specifically before the very first "goto fail", or make changes to the rules (but not the syntax, and (I think) not the semantics) of how goto works in Go, and allow it to jump over var definitions. The first would allow us to make it work now. The latter would lead to a better structuring of a program, basically as it is now in Go, not deviate it to the enforcement of where exactly the vars should be defined in a scope. But to implement it, careful analysis of consequences is required. |
To be honest, I am new to Go, and don't know the internals of its compiler, so it's totally unknown to me why authors decided to forbid jumping over var defs with goto. Probably it was specifically to discourage people from arbitrarily using the goto? Because, technically, it already works, but in different construct:
It works. So, why goto can't? After all, all these implicit definitions are "hoisted" up the scope, aren't they? And this example with for and break works. So, there should be no technical problem for goto doing the same. By the way, there might be a temptation to use this for/break idiom to handle errors, but it won't work because of scope shadowing. This:
Will not print err value, because it's not assigned outside of "for" scope. But would you make this change, it will start working the right way:
But then it nullifies all the convenience of ":=" syntax. Returning to the main subject, I am certain that there should be no technical problem for lifting up the restriction of goto jumping over the variable definitions. |
Ughhh... After drinking a cup of tea, I figured it out that my proposal with gotos will suffer from scope shadowing as well. Here's an example:
The solution for this problem would be the unlikely one to be approved.... To make "err" (or "e" or "_e") an exception of scoping rules, to make it always in the scope of a function, just like labels are. The moment we do so, not only "goto"-based approach will work, but also for/break idiom as well. As of now, I am 80% sure that this proposal will be dismissed. Yet, I simply so much like the beauty of the simplified code it might lead to, that I gonna type it here once more.
and
Hope some will value it too. |
I just watched a video "Gopherpalooza 2018 - Ian Lance Taylor: Transition to Go 2". In this context, the changes proposed:
|
Here's just another way to handle this (and also an illustration that this bothers not only me). Found on astaxie: Build web application with Golang. Here's a snippet of code:
and the
It does the job. But, it's not perfectly efficient, because it needs additional function call each time, just to check a condition. I know, inline functions exist, and probably Go compiler does inlining, I don't know, but still... It's also an answer to those who say that "there is no cases where there are many error check needed in sequence", or something like that. Here are 6 calls to |
I would like to mention that this breaks a proverb of Go - "errors are values". Errors in Go do not have any special treatment other than being a predeclared interface.
It's to prevent this case:
Any time you jump forward in a block with a
If this is made a keyword (or an operator), it would technically be a breaking change, as |
Hi @deanveloper, I actually tried it. To make it compilable, let's transform it to its equivalent form:
So, what get's printed? This:
I'll explain further. The Go already has clear definition of what defined but not initialized variables hold, a "zero values". Here it is, right from the Tour of Go:
I think that the decision to prevent goto from jumping over var defs, was someone's impulsive temptation "to make it a little more safer". But you can't make it totally idiot-safe, or otherwise it'll lose all expressive power and become a dull language-for-itself. And still it won't be totally safe against programmers who don't know what they are doing. There were many efforts towards that, e.g. Ada, e.g. Java. The result? Here's Go. |
that is not it's equivalent form.
that does not compile because you skip over the Variables in Go are not hoisted like they are in some other languages (ie JavaScript), so you cannot use variables until they are defined. If the definition is skipped over because of the use of a
The issue is not that the variable does not get initialized, it's that the variable does not get defined. For instance, the following compiles fine:
This is because x gets defined outside of the goto. |
Too bad. I thought they are hoisted. |
I took a closer look into it. The lang ref doesn't say a word if it is hoisted or not, I wasn't able to find there any clarification. The implementation doesn't do hoisting, though, that's the fact. @deanveloper was right. This doesn't compile:
What can I say? Too bad. I think that making Go hoist variables would be too much re-design work and effort, to just allow save someone, here and there, sporadically, few lines of code. I think that it should have been designed properly from the beginning. Still, I am sincerely glad that Go as it is exists. And I close this issue. |
Aggregate error handling
A lot of people already tried to raise a question to improve close-to-perfect error handling in Go in one way or another, so my apologies that I do it once again! I totally agree to the consensus that it's already good as it is now. However, there's this quite typical case, where the same code is typed all over again, polluting the screen, and making what otherwise would fit in half the screen, to span two screens. Here it is, in shortest form:
or this:
As you can see, the same thing is repeatedly typed again and again. And it's not just typing, it also consumes valuable space on the screen, and disperses the focus of attention.
The proposal:
Here's an example how it might look like. Let's take the first code example from above, and re-write it:
In effect this would unfold into (be equivalent of) this standard Go syntax:
Imagine how it would affect the code, if there are not two, but (as it is typically) 4..10 of them.
P.S. God bless the absence of try/catch blocks in Go.
The text was updated successfully, but these errors were encountered: