Question

Knowing full well about the eternal discussion about whether it is good practice to use GOTO (GOTO still considered harmful?), what I'm trying to ask here is if there are some drawbacks in using GOTO, specifically in CMD/DOS shell.

By drawbacks I mean if there is some loss of performance or some situations where extensive use of GOTO could end up terminating my script (as the behavior described later). I know, because TI-BASIC has no good way to create structured programs without it, that repetitive usage of GOTO in that platform will eventually drain the memory. The following quote from TIBasicDev explains this behavior:

Using a Goto to exit any block of code requiring an End command causes a memory leak, which will not be usable until the program finishes running or executes a Return command, and which will slow down your program down.

The other "way" of looping through commands in CMD is through FOR statements, that are remarkably specific about their expected arguments and as such can not be used in any situation.

Was it helpful?

Solution

GOTO in a Windows batch script is generally safe to use, and sometimes necessary. But there are three non-intuitive design features that are worth noting:

1) Do not GOTO a label placed within a parenthesized block of code

You can GOTO a label placed within a parenthesized block, but it will probably not give you the result you intend. For example, a GOTO within a FOR loop DO block will immediately terminate the loop. If the GOTO references a label within the DO block, control is transferred correctly to the label location, but the batch parser now knows nothing about the FOR loop context. The code will be executed as if it is not within a loop. See the accepted answer to (Windows batch) Goto within if block behaves very strangely for more information.

2) Location of the label can affect performance.

This is generally not an issue unless you are dealing with a really large script.

When performing a GOTO :label (or CALL :label), the batch processor begins scanning from the current script location, looking for the first occurrence of :label. If it reaches the end of the file without finding the label, then it loops back to the top and continues the search. An error will be raised if it reaches the starting point without finding the label. So performance can sometimes be improved in very large scripts by structuring the script such that labels appear shortly after their respective GOTO (or CALL). Of course, if a label is referenced from many locations, that may be impossible.

3) The same label can actually be safely used in multiple locations (not advised)

Once you understand the label scan process described in point 2 above, you can safely reuse a label if you are careful.

For example, the following script will work properly:

@echo off

for %%A in (1 2 3 X Y Z) do (
  echo %%A
  if %%A equ 3 goto break
)
:break

for %%A in (A B C 8 9 10) do (
  echo %%A
  if %%A equ C goto break
)
:break

-- OUTPUT --

1
2
3
A
B
C

Although reuse of labels works, it is not a good practice since it could confuse anyone else that tries to interpret or debug the script.

OTHER TIPS

GOTO :label is an integral part of batch coding and has no built-in drawbacks - it is a necessary part of batch scripting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top