Is Using a 'Goto' Statement Bad

What is wrong with using goto?

Because they lead to spaghetti code.

In the past, programming languages didn't have while loops, if statements, etc., and programmers used goto to make up the logic of their programs. It lead to an unmaintainable mess.

That's why the CS gods created methods, conditionals and loops. Structured programming was a revolution at the time.

gotos are appropriate in a few places, such as for jumping out of nested loops.

Is using a 'goto' statement bad?

EDIT:

How bad is the goto statement really, and why?

It depends on the exact situation. I can't remember any time where I found it made the code more readable than refactoring. It also depends on your personal view of readability - some people dislike it more than others, as is clear from the other answers. (As a point of interest, it's widely used in generated code - all of the async/await code in C# 5 is based on effectively a lot of gotos).

The problem is that situations where goto tends to be used tend to be the kind of situations where refactoring aids things anyway - whereas goto sticks with a solution which becomes harder to follow as the code gets more complicated.

Is there a more effective way to break the main loop than using the 'goto' statement?

Absolutely. Extract your method out into a separate function:

while (ProcessValues(...))
{
// Body left deliberately empty
}

...

private bool ProcessValues()
{
for (int i = 0; i < 15; i++)
{
// Do something
return false;
}
return true;
}

I generally prefer doing this over introducing an extra local variable to keep track of "have I finished" - although that will work too, of course.

Why is it not good practice to use 'goto'?

Spaghetti is a code poorly structured and which makes it hard to update because of multiple undocumented and unexpected links or dependencies. You touch it in one place and you see other things get broken or modified in an unexpected way. Just like sticky spaghetti, you pull one end and you see a number of places start moving.
GOTO usually violates the principles of structured, procedural programming, hence the term, which suggests the tangled and arbitrary nature of the program flow.

GOTO still considered harmful?

The following statements are generalizations; while it is always possible to plead exception, it usually (in my experience and humble opinion) isn't worth the risks.

  1. Unconstrained use of memory addresses (either GOTO or raw pointers) provides too many opportunities to make easily avoidable mistakes.
  2. The more ways there are to arrive at a particular "location" in the code, the less confident one can be about what the state of the system is at that point. (See below.)
  3. Structured programming IMHO is less about "avoiding GOTOs" and more about making the structure of the code match the structure of the data. For example, a repeating data structure (e.g. array, sequential file, etc.) is naturally processed by a repeated unit of code. Having built-in structures (e.g. while, for, until, for-each, etc.) allows the programmer to avoid the tedium of repeating the same cliched code patterns.
  4. Even if GOTO is low-level implementation detail (not always the case!) it's below the level that the programmer should be thinking. How many programmers balance their personal checkbooks in raw binary? How many programmers worry about which sector on the disk contains a particular record, instead of just providing a key to a database engine (and how many ways could things go wrong if we really wrote all of our programs in terms of physical disk sectors)?

Footnotes to the above:

Regarding point 2, consider the following code:

    a = b + 1
/* do something with a */

At the "do something" point in the code, we can state with high confidence that a is greater than b. (Yes, I'm ignoring the possibility of untrapped integer overflow. Let's not bog down a simple example.)

On the other hand, if the code had read this way:

    ...
goto 10
...
a = b + 1
10: /* do something with a */
...
goto 10
...

The multiplicity of ways to get to label 10 means that we have to work much harder to be confident about the relationships between a and b at that point. (In fact, in the general case it's undecideable!)

Regarding point 4, the whole notion of "going someplace" in the code is just a metaphor. Nothing is really "going" anywhere inside the CPU except electrons and photons (for the waste heat). Sometimes we give up a metaphor for another, more useful, one. I recall encountering (a few decades ago!) a language where

    if (some condition) {
action-1
} else {
action-2
}

was implemented on a virtual machine by compiling action-1 and action-2 as out-of-line parameterless routines, then using a single two-argument VM opcode which used the boolean value of the condition to invoke one or the other. The concept was simply "choose what to invoke now" rather than "go here or go there". Again, just a change of metaphor.

Understand the pro and cons of the GoTo statement

Your code can be easily re-written as below:

Private Sub SaveButton_Click()

Dim i As Integer

'mandatory textboxes:
For i = 1 To 13
If UserForm1.Controls("Textbox" & i) = "" Then
MsgBox "Please fill in every mandatory textbox"
Exit Sub
End If
Next

End Sub

Don't ever use GoTo unless it is behind On Error … or not avoidable. If there is any chance to avoid GoTo, then avoid it. It makes your code hard to maintain and is considered to be a bad practice.

As GSerg pointed out there might be rare cases where GoTo cannot be avoided. Eg. using GoTo for emulating missing language constructs (e.g. VBA lacks the Continue keyword) and exiting deeply nested loops prematurely.

Why not GOTO Statement?

At least for some programming languages (none of which I'm the designer of, obviously) like C and C++, I imagine it's there because it

  1. Closely models what the hardware really can do, which is kind of the goal in these languages.
  2. Is sometimes actually useful and better than more "structured" approaches.

The most common example of when goto is often considered good is when doing nested error/resource management in C. See for instance the Linux kernel, a fairly large and successful C project which uses goto for this purpose.

Are there any legitimate use-cases for goto in a language that supports loops and functions?

There are a few reasons for using the "goto" statement that I'm aware of (some have spoken to this already):

Cleanly exiting a function

Often in a function, you may allocate resources and need to exit in multiple places. Programmers can simplify their code by putting the resource cleanup code at the end of the function, and all "exit points" of the function would goto the cleanup label. This way, you don't have to write cleanup code at every "exit point" of the function.

Exiting nested loops

If you're in a nested loop and need to break out of all loops, a goto can make this much cleaner and simpler than break statements and if-checks.

Low-level performance improvements

This is only valid in perf-critical code, but goto statements execute very quickly and can give you a boost when moving through a function. This is a double-edged sword, however, because a compiler typically cannot optimize code that contains gotos.

Note that in all these examples, gotos are restricted to the scope of a single function.

To GOTO or not to GOTO?

I am not sure what do you mean by clean up code but in C++ there is a concept called "resource acquisition is initialization" and it should be the responsibility of your destructors to clean up stuff.

(Note that in C# and Java, this is usually solved by try/finally)

For more info check out this page:
http://www.research.att.com/~bs/bs_faq2.html#finally

EDIT: Let me clear this up a little bit.

Consider the following code:

void MyMethod()
{
MyClass *myInstance = new MyClass("myParameter");
/* Your code here */
delete myInstance;
}

The problem: What happens if you have multiple exits from the function? You have to keep track of each exit and delete your objects at all possible exits! Otherwise, you will have memory leaks and zombie resources, right?

The solution: Use object references instead, as they get cleaned up automatically when the control leaves the scope.

void MyMethod()
{
MyClass myInstance("myParameter");
/* Your code here */
/* You don't need delete - myInstance will be destructed and deleted
* automatically on function exit */
}

Oh yes, and use std::unique_ptr or something similar because the example above as it is is obviously imperfect.

Are goto statements efficient when compared to calling functions?


Do the goto statements translate directly into machine code which tells the computer just to JUMP to a different memory address?

Yes.

Is this a lower cost in the machine to jump around like this when compared with the cost to call a function?

Yes.

However, when the compiler sees a function call, it doesn't have to actually generate code to call a function. It can take the guts of the function and stick them right in where the call was, not even a jump. So it could be more efficient to call a function!

Additionally, the smaller your code, the more efficient it will be (generally speaking), since it is more likely to fit in the CPU cache. The compiler can see this, and can determine when a function is small and it's better to inline it, or when it's big and better to separate it and make it a real function, to generate the fastest code (if you have it set to generate the fastest code possible). You can't see this, so you guess and probably guess wrong.

And those are just some of the obvious ones. There are so many other optimisations a compiler can do. Let the compiler decide. it's smarter than you. It's smarter than me. The compiler knows all. Seriously, Cthulhu is probably a compiler.

You said not to, but I'm going to say it: I highly advise you to profile your code before deciding to do this, I can almost guarantee it's not worth your time. The compiler (most of which are near-AI level smart) can probably generate as fast or faster code with regular function calls, not to mention the maintenance aspect.

Why does Go have a goto statement?

When we actually check the source code of the Go standard library, we can see where gotos are actually well applied.

For example, in the math/gamma.go file, the goto statement is used:

  for x < 0 {
if x > -1e-09 {
goto small
}
z = z / x
x = x + 1
}
for x < 2 {
if x < 1e-09 {
goto small
}
z = z / x
x = x + 1
}

if x == 2 {
return z
}

x = x - 2
p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
return z * p / q

small:
if x == 0 {
return Inf(1)
}
return z / ((1 + Euler*x) * x)
}

The goto in this case saves us from introducing another (boolean) variable used just for control-flow, checked for at the end. In this case, the goto statement makes the code actually better to read and easier follow (quite in contrary to the argument against goto you mentioned).

Also note, that the goto statement has a very specific use-case. The language specification on goto states that it may not jump over variables coming into scope (being declared), and it may not jump into other (code-)blocks.



Related Topics



Leave a reply



Submit