Sign in to follow this  

GOTO, why are you adverse to using it

This topic is 1186 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am an old school programmer, did many stints in assembly (6502,6510,68000,68030,486,586), basic, fortran, pascal, extended languages, c++, c# etc... I use goto on a regular basis to exit out of routines, skipping many lines of code and only incurring a single cache hit. In over 30+ years I know when the proper use of the command is needed, it's no worse than BREAK or CONTINUE for a loop, actually less in fact. What is your aversion to using that command, is it your workplace or your training? I can skip a thousand lines of code with a single command and a single cache hit. Do you have to jump through hoops to get out of a routine? With my experience I know when to use it and not to use it. I want to hear from the professionals why it's such a bad command to use. My typical use is goto ex; which is jump to the exit routine, everything is done, clean up and get out. I'm not a pro by any means (mid-south US, no programming jobs here), just wondering about all the hate on goto is about, it's a very useful command...

Share this post


Link to post
Share on other sites

I have no aversion. The way I write code means a goto is never necessary. I've never ran into a problem and thought to myself that a goto would be cleanest solution in C#, Javascript or C++. Maybe it's useful outside of those languages. I remember seeing it used in C and that's it. I use lambdas a lot and lambda callbacks rather than returns. It's very flexible especially with asynchronous stuff.

Edited by Sirisian

Share this post


Link to post
Share on other sites
This argument just came up on the ISOCPP mailing lists a few weeks ago, actually. The specifics were arguments for multi-level break but comparisons to goto came up of course.

Ultimately, the problem is reasoning about the structure of code. I need to read and maintain code far, far, far more often than I give any remote concern to using "a single command and a single cache hit," even in performance-sensitive domains like gaming. Gotos make it hard to tell not only where code flow might go but how the code flow can reach a particular point.

This is also why some of us despise exceptions with a complete and utter passion.

Share this post


Link to post
Share on other sites

When I first learned to program is was with basic and GOTO was all we had.  I understand they can have their uses, but along with line #'s I'm quite glad to see them generally regulated to the annuls of history.  But unlike Sean, I LOVE exceptions.  I guess to each is own ;)

Share this post


Link to post
Share on other sites

I do rarely use goto, in C++ and even C#.

 

This is if I have a few nested loops and on occasion need to restart the whole shebang or for multi level break. I try to keep the target on the same screen as the goto call though.

 

Yes, some academics would then explode that code into 5 sub functions and thus shred related code to pieces. This does NOT increase readability IMHO.

 

 

Also, I despise exceptions. They make people lazy (I have a problem, let's pass it to someone else). In some cases they help have "cleaner" code. Until you really try to have exception clean code. On the top level you would have to try/catch every single line by itself, unless you can assure there are NO side effects if one of the sub steps fails.

Share this post


Link to post
Share on other sites

Saying GOTO is harmful is like saying chopsticks are harmful. GOTO is a tool which is good for some things and not so good for others. Saying "GOTO can't be used ever for anything because it's bad, m'kay?" is silly.

 

Personally, I often prefer to use GOTO liberally while writing driver and other low level code in C. Here, I regularly write functions consisting of longish sequences of steps involving HW states and kernel resources. Each of these steps need to succeed and the only "else" action for any of the individual steps failing is to roll back everything done so far much more carefully than what I could get away with in "application/user mode code". Due to being limited to C, I can't rely on RAII, destructors, exceptions and stuff like that to clean up after me when something goes wrong.

 

Why not if-else or nested functions? A 25 step function would lead to 25 nested if-else statements or 25 nested function calls. I consider this worse from maintainability and "code esthetic" points of view than repeating 25 times "do something; if (failed) goto RECOVER;" with a roll-back section at the end of the function.

 

That said, I practically never use GOTO in/with higher level code/languages (C++, C#, Java, etc.) where I rely on the in-voque mechanisms of garbage collection, RAII, exceptions (and, like most user mode code developers, perhaps unconsciously, eventually the OS cleaning up my mess after my process crashes).

 

Share this post


Link to post
Share on other sites

When I had a Pascal course back in 1991, the teacher we had enforced strict prohibition to gotos, arguing that you should be able to draw a flow chart from top to bottom with no crossing line of flow.  Goto obviously breaks this.  I never used goto since then, and I actually never had any need to use goto either, but I do break the flow according to flow charts every day:

 

Break and continue breaks the flow, so does early exits with return, so as far as I am concerned, if goto is considered evil, so is break, continue and premature returns too.

 

Edit:

 

Multi level break is a problem of course.  I think Swift has solved that by labelling the loops so you could name the loop you wanted to break, ie. 'break columnLoop', for instance.

Edited by aregee

Share this post


Link to post
Share on other sites

I can skip a thousand lines of code with a single command and a single cache hit.

If you have 1000 LoC long functions, that is probably equally bad.

Something that I have seen, and I wonder if it's prejudice or actually founded, is that "older" programmers tend to distrust the compiler, specifically its optimization capabilities. Its probably because they have seen the really bad first generations of high level language compilers. But somehow this seems to stick. I still see people trying to reuse local variables to save the compiler the trouble of expanding and reducing the stack frame (Yes, authors of "Numerical Recipes", I'm looking at you). You don't need to do that anymore.
Similarly I'm pretty sure I have seen a compiler reducing a series of break; statements into a single jump.

This means that you can actually use high level constructs like classes without having to fear immediate performance penalties. And with that comes the realization, as others pointed out, that there are a ton of different mechanisms to choose from so that GOTO simply isn't necessary anymore. I think the only place I ever used it was for error handling in pure C, similarly to what chingo wrote.

Share this post


Link to post
Share on other sites

At the asm level, everything is a goto, so they're obviously not the devil. The argument is that certain uses have a structure -- if/then/else, for/break/do/while, switch, call -- and that this structure makes programs easier to reason about. Without any structure, programs are just spaghetti.

This is obvious at the time, but it was something that actually had to be explained back then -- structured flow control is better than spaghetti. High level flow control patterns are a good thing.

 

Goto usually isn't required in high-level programming because we've formalized all the useful uses of it into flow control keywords already.

 

I agree with this, and just want to add that the same can be said for other parts of programming languages that are considered harmful. Depending on that section of code's abstraction, you stop using some features to use other higher-level features.

 

malloc() is considered harmful in C++ when dealing with classes, if you aren't writing at a really low level, so use new and delete instead.

new and delete is considered harmful in C++ if you aren't writing low-level code. Use containers (like std::vector) and smart pointers (like std::unique_ptr) instead.

 

Goto is considered harmful... if you're working at with real basic languages lacking more advanced flow control.

 

For example, I've used GOTO in VBA and also in a custom game scripting language someone wrote I had to use for a hobbyist team project. It made sense and was the cleanest solutions in those circumstances. I've used it very few times in C++, but the C++ usages usually turned out to be because the code wasn't structured right in the first place.

Share this post


Link to post
Share on other sites
In C++ Goto has well-defined behavior, but several restrictions to avoid breaking the language. You will generally have cleaner code if you use other language features (functions, RAII, etc) to do whatever you're trying to accomplish with goto in a way that the code maintainer will be able to understand. In my place of work, goto would result in immediate code review fail because of this.

Note that if you're using C... well... that is less safe.

Share this post


Link to post
Share on other sites
goto breaks the flow of the program and makes significantly harder to track or predict how a program will execute by just glancing at the code. It also makes silly bugs and mistakes much easier to introduce.
It basically reverts any language back to assembly-level difficulty where you have to follow instruction by instruction to see how the execution jumps around; except that its even harder because in assembly at least you've got an instruction per line; whereas in other languages one expression could be expanded to multiple statements.
I cannot simply place my finger at a random place, start from there, and understand what's going on. Code with goto forces me to go to the start.

Comparing with continue and break is not fair, because continue and break have very clear flow of the program: Just jump your eyes to the bottom of the ending bracket '}' (unless you have deeply nested break and/or continue statements, which is also hard to track and also considered a bad practice anyway). If the code inside the brackets is too long and you have to scroll down too much, again... you're doing it wrong.

goto on the other hand, can jump anywhere, like a flea. It may jump backwards a couple lines. It may jump backwards a thousand lines, then jump again forward another couple thousand lines. You never know where it's going to land and it's very distracting. Not to mention you have to keep a mental model of the state of the program before each jump.
May be you think writing code with goto is easy and convenient. And indeed it is. But when you have to maintain that code a year after you wrote it, or collaborate with other people who need to read and understand what you wrote; goto becomes a nightmare. Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

Something that I have seen, and I wonder if it's prejudice or actually founded, is that "older" programmers tend to distrust the compiler, specifically its optimization capabilities. Its probably because they have seen the really bad first generations of high level language compilers. But somehow this seems to stick. I still see people trying to reuse local variables to save the compiler the trouble of expanding and reducing the stack frame (Yes, authors of "Numerical Recipes", I'm looking at you). You don't need to do that anymore.
Similarly I'm pretty sure I have seen a compiler reducing a series of break; statements into a single jump.

I disagree on two points with that statement.
First I've found "older" programmers tend to avoid goto like the plague; and second, their distrust for the compiler is justified (it's not based just on "first generation" experiences). But they don't resort to gotos.

Share this post


Link to post
Share on other sites

 

Something that I have seen, and I wonder if it's prejudice or actually founded, is that "older" programmers tend to distrust the compiler, specifically its optimization capabilities. Its probably because they have seen the really bad first generations of high level language compilers. But somehow this seems to stick. I still see people trying to reuse local variables to save the compiler the trouble of expanding and reducing the stack frame (Yes, authors of "Numerical Recipes", I'm looking at you). You don't need to do that anymore.
Similarly I'm pretty sure I have seen a compiler reducing a series of break; statements into a single jump.

I disagree on two points with that statement.
First I've found "older" programmers tend to avoid goto like the plague; and second, their distrust for the compiler is justified (it's not based just on "first generation" experiences). But they don't resort to gotos.

 

 

Do you have any examples of the sorts of circumstances under which more modern compilers are untrustworthy?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites

Do you have any examples of the sorts of circumstances under which more modern compilers are untrustworthy?

It took them years to get the compilers right on the last gen of consoles, at least. Sony spent at least half of the generation simultaneously shipping two independent compilers (common linker) as part of the PS3 dev kit.

Edited by Promit

Share this post


Link to post
Share on other sites

Do you have any examples of the sorts of circumstances under which more modern compilers are untrustworthy?


On Android (and in extremely rare circumstances) the Mono JIT compiler can produce corrupted interface method tables which result in undefined behavior instead of just crashing.

On iOS, Mono's AOT compiler inconsistently generates either correct or incorrect code when using highly important generic interfaces such as IEnumerable<T> (especially when an array is involved).

(Both of these may be Unity-specific as Unity uses a very old version of Mono) Edited by Nypyren

Share this post


Link to post
Share on other sites

This topic is 1186 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this