Are GOTO Statements Still Dirty?

November 13, 2009 by datapig Leave a reply »

A long time ago, someone deemed that the GOTO statement is evil and should never be used. Since then, the unwritten rule in programming is to stay away from GOTO statements at all costs.

Despite this, I have to confess that I use the GOTO statement all the time. I love using it. But given the widespread distain for it among programmers, I feel dirty when I use it.

In fact, when I use the GOTO statement, I'm typically wearing nothing but a long brown raincoat and black socks.

 

For those of you who don't know, the GOTO statement tells your code to jump to another place in your procedure (usually defined using labeling) and start executing statements from that point. It's typically used in Error handling – for example:

Sub AddDirectory()
On Error GoTo MyErr
MkDir "C:\Temp"
Exit Sub
MyErr:
MsgBox "That Directory already exists."
End Sub

The GOTO statement here tells the code to jump to the MyErr label and start executing the code after that label. In this case, if an error occurs, then a message box is activated.

 

Outside of using them for error handling, GOTO statements are frowned upon. The most commonly expressed reason is that GOTO statements lead to spaghetti code. That is to say, GOTO statements have no inherent context that mandates where your code should go next. The thought is that a liberal use of GOTO statements could have your code jumping from here, to there, to another there, back to here again. Also, there is a possibility that GOTO statements can cause infinite loops and lost variables if nested incorrectly in looping procedures.

 

All that sound pretty evil right? In fact, similar to DLL Hell, I'd like to be the first to coin the term, "GOTO Hell" – mainly because it sounds funny.

 

Despite all the evil sounding stuff, I use them anyway.

 

First off, it's true that if you use GOTO statements everywhere, you'll end up with spaghetti code. But I've seen lots of spaghetti code that didn't involve GOTO statements. Can anyone say Call Statement? A Call statement allows you to jump to another procedure or function from the current one. It's used quite often in programming although it essentially performs the same function as the GOTO statement. For example, this procedure jumps to Macro 1, then jumps to Macro2, then Macro3, then Macro 4. In addition to all that jumping, this procedure does its own stuff.

Sub Macro5()
'Do some stuff
Call Macro 1
'Do some stuff
Call Macro 2
Call Macro 3
'Do more stuff
Call Macro4
End Sub

 

So how is that different from the GOTO statement? If you're using Call statements, then you're using GOTO. You're just as dirty as I am…you filthy wicked monkey.

The truth is, anyone can be an Ass about their code even without the GOTO statement. GOTO statements don't kill code, people kill code.

 

Here is an example how I use GOTO:

For MonthNum = 1 To 12
If Me.Controls(MonthNum).Enabled = False Then
GoTo Skip
End If

If MonthNum <= CommitedMonth Then
Me.Controls(MonthNum).Value = ProjectionFigure
Me.UpdateDate = Now()
Else
Me.Controls(MonthNum).Value = 0
End If
Skip:
Next MonthNum
Exit Sub

 

The alternative way to write this without GOTO is:

For MonthNum = 1 To 12
If Me.Controls(MonthNum).Enabled = True Then
If MonthNum <= CommitedMonth Then
Me.Controls(MonthNum).Value = ProjectionFigure
Me.UpdateDate = Now()
Else
Me.Controls(MonthNum).Value = 0
End If
End If
Next MonthNum
Exit Sub

 

I actually find the version with the GOTO easier to read. With the GOTO statement in place, I can see very clearly what exactly happens when the condition is not met.

In the GOTO-less alternative, I've got to scan through a bunch of code to determine what happens when the initial condition is not met.

 

In the end, I don't think that the GOTO statement will kill your code. I say as long as you can make your code work, and you can easily relay your logic to the next developer, use whatever you want.

Advertisement

11 Responses

  1. JP says:

    I agree with you, and I do the same thing with GoTo. Suppose you're looping through a folder looking for specific files. You don't want to exit the loop just because you found a non-matching file, so you need a way to skip to the end of the loop without breaking out. The GoTo statement meets that need. As long as it's the exception, not the rule, you should be fine.

  2. dermotb says:

    I would prefer........
    If Me.Controls(MonthNum).Enabled = False Then
    'do nothing if False
    Else
    'the rest of your code

  3. Bob Phillips says:

    Whilst I agree with your overall thrust, I disagree on epecifics, namely
    - Call is NOT the same as GOTO. Call has an implicit return to the following statement (unless it errors), GOTO does not, and you are unlikely to see a called statement calling back to the caller, which is the sort of really nasty thing you can see with GOTO
    - I think your exampls sans GOTo is much clearer than the the one with GOTO.

    I prefer to compare Goto to something like an Exit For, Exit Do, they both break the flow just as badly as Goto, yet I rarely hear anyone suggesting that anyone using these should bedeported to Siberia.

    I have been making this argument for years (an example see http://excelusergroup.org/forums/p/1211/3716.aspx, which was actually an argument raised because the Pig offered some code with a GOTO in it :) ), and it seems to be catching on. This worries me, I might have to change sides.

    Oh, and tell me how anyone who wallows in mud eating bacon can possibly accuse Goto statements of being dirty.

  4. datapig says:

    Bob: Ahhh....I remember that thread. I can't believe that was way back in March! Time really puts a beating on us, doesn't it.

  5. GOTO is like crack. If you just use a little bit in the morning, you're fine. But it never goes that way, does it? Before you know it, you're strung out on spaghetti code and deleting Option Explicit from your modules.

    I think an important distinction with Exit For/Do, is that those can only move forward and only to a certain spot. I'm not sure what the alternative to Exit For is if I've found the only element in a loop other than finishing the loop.

  6. XL-Dennis says:

    Mike,

    Sorry, but You're not the first to coint GOTO Hell. The first time I saw it, If my memory don't trick me, was the Vain in VB's newsgroups. In fact he used it in his signature: "On Error GOTO Hell".

    GOTO supports the paradigm to have only one exit point in all VBA methods. At the same time it's an old approach and should only be used with classic VB and VBA. In VB.NET we have much better options as it's a model language.

    Kind regards,
    Dennis

  7. kzutter says:

    Sorry Data Pig, you got it wrong this time...

    Call is not the same as GOTO!

    Call returns, GOTO does not.

    The cool thing about Call is that you can wrap the argument list in parens even if you are not using the returned value. This is handy for us that use 'real' programming languages and are accustomed to using parens.

    There is nothing wrong with using Call, in fact sometimes it is necessary!

  8. Ajay says:

    I feel goto statements are an excuse more than anything else. If used for error handling (and which is where I've used them most), one is essentially covering one's back beacuse MS did not provide better error handling constructs. If used otherwise, it is often because one did not anticipate that particular situation to occur when one started writing the code and then by that time, having written so much code, was lazy to go back and restructure it.

    Regards,
    Ajay

  9. Jon Peltier says:

    Call does not create spaghetti code. Call branches to another routine, then returns. It's really no different than calling a function except for not returning a value.

    Spaghetti code is where execution jumps around from place to place in a single procedure, so that tracking it is like trying to untangle a mass of spaghetti. Overcooked spaghetti, because if you pull on a strand too hard, it breaks, and you lose track of where you are.

  10. ross says:

    GoTo's are like Beers. If you have to many bad things happen, if you don't allow yourself any, you just being prudish, but at the right time and place they are just the ticket.

    But in VB you shouldn't really use them to go backwards!

Leave a Reply