The Go language will not be adding a "try" keyword in the next major version, despite this being a major part of what was proposed for version 1.14.
Go, an open source language developed by Google, features static typing and native code compilation. It is around the 15th most popular language according to the Redmonk rankings.
Error handling in Go is currently based on using if statements to compare a returned error value to nil. If it is nil, no error occurred. This requires developers to write a lot of if statements.
"In general Go programs have too much code-checking errors and not enough code handling them," wrote Google principal engineer Russ Cox in an overview of the error-handling problem in Go.
A try statement was proposed to help reduce the coding burden. Upon further reflection:
That proposal has now been abandoned. Robert Griesemer, one of the original designers of Go, announced the decision in a post yesterday.
[...] “Making an exit point of a function that isn't a return, and is meant to be commonplace, may lead to much less readable code,” said one user.
The outcome is a good one insofar as the Go community has proved able to make and withdraw a major proposal without rancour. And as for error handling, no doubt the team will, um, try again.
(Score: 0) by Anonymous Coward on Wednesday July 17 2019, @06:35PM (33 children)
I wish there were a way to break to a specific block level.
break (2) ==> break out 2 levels from the inside
break (-1) ==> break to the top level of the procedure minus one
(Score: 2) by DannyB on Wednesday July 17 2019, @06:38PM
Maybe I Miss. Understand. But that sounds like a procedure would need to have some idea of who was calling it.
People today are educated enough to repeat what they are taught but not to question what they are taught.
(Score: 1) by nitehawk214 on Wednesday July 17 2019, @06:53PM (18 children)
I had a friend that advocated this. Java has a "break with label" which is really just a goto. C# also supports a direct goto, as does most other c-derived languages.
I don't even recall the last time I used a break statement outside of a switch. I used to use them all the time; but with more languages supporting advanced collections and lambdas, it leans to cleaner code not using breaks.
"Don't you ever miss the days when you used to be nostalgic?" -Loiosh
(Score: 2) by tangomargarine on Wednesday July 17 2019, @07:09PM (10 children)
Not exactly. From what I understand, you can only use it to descope to a later line number, within the same function. It's very much not an unconditional jump.
"Is that really true?" "I just spent the last hour telling you to think for yourself! Didn't you hear anything I said?"
(Score: 2) by DannyB on Wednesday July 17 2019, @07:36PM (9 children)
According to this [geeksforgeeks.org]. You can use continue instead of break. You can jump backward as well as forward. You do not have to do it within a switch statement.
It is restricted to be within the same function. But I do not see any obviously useful porpoise for being able to 'goto' outside of the current function.
People today are educated enough to repeat what they are taught but not to question what they are taught.
(Score: 2) by All Your Lawn Are Belong To Us on Wednesday July 17 2019, @07:59PM (3 children)
If you want to goto outside of a function then why not use a function call or a GOSUB. Porpoises like to travel with subs after all.
(And more seriously, I suppose if you wanted to terminate a running function and purposely drive yourself somewhere other than what called it you'd want a goto.... otherwise why not jump to the bottom of your function and let it terminate naturally... ? )
This sig for rent.
(Score: 2) by tangomargarine on Wednesday July 17 2019, @08:52PM (1 child)
The obvious answer is, because that doesn't let you discard your context. But good practice means that should be a rare desire anyway.
If you absolutely feel you *need* a goto in Java, you can somewhat cumbersomely simulate it with a try-catch and purposely throwing an Exception. Which is also basically a comefrom [wikipedia.org] :)
"Is that really true?" "I just spent the last hour telling you to think for yourself! Didn't you hear anything I said?"
(Score: 2) by All Your Lawn Are Belong To Us on Wednesday July 17 2019, @10:19PM
Indeed. But if you execute COMEFROM, should you not also execute an IFKTR [faisal.com] as well?
This sig for rent.
(Score: 1, Redundant) by DannyB on Thursday July 18 2019, @01:10PM
I would replace all GOTO with GOSUB for reasons of artistry and fashion.
People today are educated enough to repeat what they are taught but not to question what they are taught.
(Score: 2) by tangomargarine on Wednesday July 17 2019, @08:55PM (4 children)
It doesn't "jump backward" any more than to the top of the nested block you're in, though. To be "really just a goto" you need to be able to jump to an arbitrary point in execution, which would include across function boundaries. It may not be super *useful* but let's not confuse our definitions by saying this is "basically goto" when it has all these restrictions built into it.
"Is that really true?" "I just spent the last hour telling you to think for yourself! Didn't you hear anything I said?"
(Score: 2) by DannyB on Thursday July 18 2019, @01:12PM (3 children)
If you can jump to any label within a certain construct, how is that not a GOTO ?
Would any GOSUB smell as sweet?
People today are educated enough to repeat what they are taught but not to question what they are taught.
(Score: 2) by tangomargarine on Thursday July 18 2019, @02:50PM (1 child)
How many more times do I have to say this?
Wikipedia:
Jump instructions [wikibooks.org] are literally "resume execution at line X". They don't care about context at all.
The Java goto is a strict subset of gotos as generally understood, since the...compiler (or whatever it is they call the thing in Java that makes bytecode) checks the context where the label you're trying to jump to is located.
Gosubs aren't gotos either. If it returns, it's a function call.
"Is that really true?" "I just spent the last hour telling you to think for yourself! Didn't you hear anything I said?"
(Score: 2) by DannyB on Thursday July 18 2019, @05:04PM
I do understand the difference between gosubs and gotos, once long ago programming WANG BASIC and TRS-80, etc.
I've never needed to use a goto in Java. (Or C, or Pascal for that matter). Structured programming really does eliminate goto's.
So I looked more closely at the link I gave, and I see that in Java the labels are more limited than I realized in where they can be placed. Surprise. But I've never need to use a goto since spring 1982. After that it was all Pascal and some bits of x86 and 68000 for me until the early 1990s.
People today are educated enough to repeat what they are taught but not to question what they are taught.
(Score: 2) by tangomargarine on Thursday July 18 2019, @02:54PM
And you can't jump to *any* label within a function either. As I said.
void foo()
{
label A:
code
code
code
label B:
while(true)
{
goto _;
}
}
Putting "B" in the blank will work. Putting "A" there will cause the compiler to yell at you.
"Is that really true?" "I just spent the last hour telling you to think for yourself! Didn't you hear anything I said?"
(Score: 3, Insightful) by Thexalon on Wednesday July 17 2019, @07:17PM (1 child)
The main upside of a "break" is to short-circuit when possible, but you're right that it's frequently unnecessary.
One refactor that also eliminates "break", especially with multiple layers, is an early "return", combined with making the inside of a block into a method. Or in pseudocode, this:
becomes this:
It's up to you whether that's better, although I generally think it is.
The only thing that stops a bad guy with a compiler is a good guy with a compiler.
(Score: 0) by Anonymous Coward on Thursday July 18 2019, @05:59AM
I usually use the nested function method. It works fine if the outer loop isn't time sensitive or the language and compiler have decent inline function support, but even then if the innermost loop needs access to the outermost loop's then other methods need to be used.
(Score: 2) by fyngyrz on Wednesday July 17 2019, @07:33PM (4 children)
I habitually use nested ifs with else clauses that handle most error cases, at least outside of Python. In Python, pretty happy with try, actually. I could learn to use it more effectively... more named exceptions, etc.
In c and c++ though, I often use the if (thingIsGood) {dostuff} else {shitmyself} form of triage. Lends itself to all kinds of things very nicely, and I can write the cleanup and error stuff almost automatically as I brace it out. Some folks don't like a lot of block nesting, but I'm okay with it.
if ((ptr1 = some_alloc(whatever)) != NULL)
{
if (ptr2 = some_alloc(whatever)) != NULL)
{
do_stuff_with_ptrs(ptr1,ptr2);
some_free(ptr2);
}
else
{
bitch_and_whine_about_ptr2_and_no_stuff_done_etc();
}
some_free(ptr1);
}
else
{
bitch_and_whine_about_ptr1_and_no_stuff_done_etc();
}
--
Surely not everybody was kung fu fighting?
(Score: 0) by Anonymous Coward on Wednesday July 17 2019, @10:26PM (2 children)
There is an obvious problem with that style of error handling: the assertion and the diagnostic message are not in the same place, so suffer from reader locality. Worse, the order of tests and diagnostics are reversed in these nested situations.
This is much better for readability (pseudo-c):
attempt
{
assert((ptr1 = some_alloc(whatever)) != NULL);
assert((ptr2 = some_alloc(whatever)) != NULL);
do_stuff_with_ptrs(ptr1,ptr2);
some_free(ptr2);
some_free(ptr1);
}
handle_assert(ptr1)
{
bitch_and_whine_about_ptr1_and_no_stuff_done_etc();
}
handle_assert(ptr2)
{
bitch_and_whine_about_ptr2_and_no_stuff_done_etc();
}
(Score: 2) by The Mighty Buzzard on Wednesday July 17 2019, @10:42PM
That's only a problem if it's not what you deal with every day.
My rights don't end where your fear begins.
(Score: 2) by fyngyrz on Thursday July 18 2019, @11:09AM
They are when they are written, though, because they're the first things to be assembled. request, test, cleanup, report. Once that's done, then you fill the code block.
Using this successfully is no more than a matter of carefully sequenced code building. Once that's ingrained, it's perfectly reliable and suffers from nothing at all.
No, they aren't. Test occurs at request time; diagnostic follows immediately if it is called for, otherwise isn't executed. It's not true in a visual read-the-code sense, either. I think you may have misread what I wrote there.
Also, sigh, missed (at least) a paren in there... I need a pseudo code compiler. :)
--
Forget world peace. Visualize using your damned turn signal.
(Score: 3, Insightful) by The Mighty Buzzard on Wednesday July 17 2019, @10:46PM
Therein lies the main reason it doesn't belong in Go. Unless you especially want Go to wind up like Perl where there are multiple commonly used ways of doing anything you can do with a language.
My rights don't end where your fear begins.
(Score: 0) by Anonymous Coward on Wednesday July 17 2019, @07:20PM
Does go have goto?
(Score: 2) by inertnet on Wednesday July 17 2019, @08:46PM (7 children)
From the docs [golang.org]:
(Score: 0) by Anonymous Coward on Wednesday July 17 2019, @08:53PM (5 children)
Oh, cool.
That seems perfectly adequate for eliminating the nest of if's without out adding a try to the language.
So, given that why would one ask for try?
(Score: 2) by Immerman on Thursday July 18 2019, @01:45AM (4 children)
From one of the proposals, not sure if this specific one as I followed a few links:
We propose a new built-in function called try, designed specifically to eliminate the boilerplate if statements typically associated with error handling in Go[...]
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))
(Score: 1) by khallow on Thursday July 18 2019, @12:13PM (3 children)
(Score: 2) by Immerman on Thursday July 18 2019, @01:36PM (2 children)
Except you can't. You can only return from the current function from within the current function. Moreover "boilerplate code" is rarely identical, which is what you need to stick it in a library. The general pattern of
if step 1 caused an error
Abort
if step 2 caused an error
Abort
//...
if step N caused an error
Abort
Is very common in a whole lot of different situations, where steps 1 through N are completely different
And some sort of language constructs that says
try to do these things
Step 1
Step 2
//...
Step N
and if there's a problem
Abort
saves a whole lot of redundant code that otherwise that both wastes programmer time to type, and decreases clarity when reading
In C you could do something like
if(Step1 == error
|| Step 2 == error
|| ...
|| Step N == error)
Abort
and rely ion the short-circuiting behavior to jump to Abort on the first error. You'll lose all information about what error occurred, but that often doesn't matter. But thanks to Go's multi-return error model I don't think there's a clean way to do that
(Score: 1) by khallow on Sunday July 21 2019, @03:41AM (1 child)
f := try {
Step 1;
Step 2;
Step 3;
...
}
(Score: 2) by Immerman on Sunday July 21 2019, @07:15PM
No, my impression (assuming I didn't end up following a link to some other proposal) was that the specific proposal was for something far less powerful or effective:
try(step1)
try(step2)
etc.
Where any failure would immediately exit the calling function with the same error. Honestly, I can't think why anyone thought that was a good idea.
Yours seems like a much better strategy to provide most of the benefit without significantly changing flow control, or being easily confused with a more typical exception-based try statement.
Of course it would typically need to be followed by an
if(f!= null){
//do error handling;
}
block, unless you also supported a catch block to replace the redundant test (since a conditional jump must have just occurred to exit the try). A catch with no "parameters" though would also be different enough to not be easily confused with another language.
And presumably, if you didn't actually care about what error is returned, you could simplify it a bit further by leaving out the f:= part. e.g.
try{
step1
step2
}
catch{
return ... , myError
}
(Score: 0) by Anonymous Coward on Wednesday July 17 2019, @11:44PM
So, Break InnerLoop would also work?
Cool
(Score: 2) by krishnoid on Wednesday July 17 2019, @08:49PM
Perl gives you the ability to jump to specific parts in a block [perl.org], with an optional label to jump further out syntactically. Breaking out of stack frames, maybe not so much.
(Score: 2) by YeaWhatevs on Wednesday July 17 2019, @09:46PM (2 children)
It's called goto ;)
I can hear the groaning already, but that would also fix go's error handling.
(Score: 2) by darkfeline on Thursday July 18 2019, @02:19AM (1 child)
Go has goto. For fuck's sake, it wouldn't hurt to do a basic amount of research would it?
Join the SDF Public Access UNIX System today!
(Score: 2) by YeaWhatevs on Wednesday July 24 2019, @03:18PM
Just did :)