Have you ever used goto in commercial software?

I remember first using goto several years ago when I first started. I can see why it's not very pleasant to use as it could easily lead to spaghetti/confusing code. Though, it's still in the language for a reason. I recently saw something like this:

1
2
3
4
5
6
7
8
-- Pseudocode -- 
for (x -> 1000)
  for (j -> 1000)
    if (some_expression_is_true) 
      do_something();
      goto Label;

Label: 


I can see this person is using it to break out of multiple for-loops. Couldn't they use break; instead?

Thank you
Angela
Last edited on
break would break out of the inner for loop (j) only. It wouldn't break out of the x loop. This can be done without using a goto using flags - but it can get messy

1
2
3
4
5
6
7
8
9
10
11
12
13
cont1 = true
for (x => 1000 while cont1)
    for (j -> 1000 while cont1)
        if (is_true)
            do()
            cont1 = false
        endif
    endfor j
endfor x
 
if (cont1 is false)
    processfalse()
endif


In some circumstances (like this) a goto can be a cleaner method. I've used goto in parsing before to easily recover from an error.
yes, but it was before the STL existed, does that count? Things were different back then.
break only breaks out of 1 layer of a loop (or switch statement).

I have never written a goto professionally (yet), but the most common -- but still very rare -- time I see goto used is when a function branches into many different paths, but most of the branches still clean something up or immediately handle a possible error condition before the function ends. I have seen this in mostly C-style C++ code. (A destructor would be an alternative here. Although I've heard people complain about destructors in cases like this because someone casually reading the code might not even realize key logic is happening in the destructor.) So pick your poison. Or instead of a goto, explicitly call a cleanup function + return.

Similar technique can be applied to nested loops. If you factor out the nested loop into its own function, you can call return while inside the nested loops, effectively doing the same thing as a goto.
Last edited on
Another way to avoid the goto in your example is to turn it into a function (or a lambda?)
1
2
3
4
5
6
7
8
9
void f() {
  for (x -> 1000)
    for (j -> 1000)
      if (some_expression_is_true) {
        do_something();
        return;
     }
  }
}


Another way which I think would be cleaner is an obvious (to me anyway) addition to the language: let break be followed by one more more control keywords that give the structures it's breaking out of:
1
2
3
4
5
for (x -> 1000)
  for (j -> 1000)
    if (some_expression_is_true) 
      do_something();
      break for for;  // break out of both enclosing for loops. 


The keywords would be optional. Without them, the behavior would be what we have today. Here are some more examples:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
while (cond) {
    for (unsigned i=0; i<10; ++i) {
        if (x) {
             break;  // today's behavior
        } else if (y) {
             break for;  // breaks out of for statement
        } else if (z) {
             break for while;  // breaks out of for and while statements
        } else if (a) {
             break while; // syntax error: nearest enclosing breakable structure isn't a while
        } else if (b) {
             break while for;  // same as above
        } else if (c) {
             break for switch;   // syntax error: second enclosing breakable structure isn't a switch.
        } else if (d) {
            break for while switch;   // syntax error: the enclosing for and while structures aren't within a switch.
        }
    }
}


So break could be followed by a list of for, do, while and switch keywords. They must match the enclosed structures and, if they do, the break would break out of all of them.
I didn't know break would only break out of an inner loop, I figured as much but never tested it to find out (silly me). I think goto receives a lot of criticism and while they are justified most of the time, there are those rare times where goto can make your code clearer and improve performance.

@dhayden's I like that kind of addition to the language, I think it can make code more readable (sometimes perhaps), it does require you to look upwards and scan for keywords though.
JavaScript allows you to label statements and mention the label when you're breaking to indicate what you want to break out of.

Something like this:
1
2
3
4
5
6
7
label_name:
while (cond1) {
    while (cond2) {
        if (cond3) 
            break label_name; // breaks outer while
    }
}


Seems like the perfect fix, but apparently even that is used very rarely. They use functions instead. (I read so in MDN)

I wonder why. It seems pretty readable to me.
I think people generally prefer to read top down. With goto, if used as discussed in this thread, you can continue looking downwards whereas with label_name you might need to scroll up to look for it.
its because early code, talking before 1990 and even back into the 70s, people had goto abuse that had you jumping all over the code everywhere and it was unreadable, couldn't be debugged easily, or modified easily -- everything people want to do with code normally (today) was in some way affected by the mess. Back then it was 1-2 guys who knew what was going on and so it was 'ok' because they knew what it did...
this behavior gave 'goto' and similar tools a bad name. They were pretty much banned from use (even when its fairly nice to do so) so much so that even your example makes some folks twist and turn the code every which way to avoid doing it. So much so that languages renamed it (eg break).
Thanks for the insight, jonnin. ;)
so much so that even your example makes some folks twist and turn the code every which way to avoid doing it


I feel a lot of C++ programmers are predisposed to do just that. Thanks for sharing this insight!
Have a read of this https://en.wikipedia.org/wiki/Goto

it's very instructive re the history.
it does require you to look upwards and scan for keywords though.
In other words, it requires you to know exactly what it's breaking out of. To me, that's a feature, not a bug.
Topic archived. No new replies allowed.