When I was just ten years old, I ventured into the world of programming without any mentor, driven solely by the pure curiosity of a child. My companion in this adventure was my lovely MSX, which was a symbol of gaming fun back then but also a gateway to the wonderful world of programming.
In the 1980s, devices like the MSX and Commodore were primarily used for gaming, predecessors to modern consoles like today's PlayStations. However, they also offered a Basic development environment, a programming language accessible even to novices.
In the 1980s, without access to the not-yet-popular Internet or the vast array of educational resources available today, I was able to explore this world with the limited tools available to me. One of these tools was the simple yet powerful GOTO construct.
With the Basic Programming Language, I learned programming fundamentals, moving between PRINT commands to display text on the screen, INPUT to acquire input from the user, and IF to control conditions. Then, there was GOTO, a command that allowed me to jump directly to a different instruction in the program.
The use of GOTO may seem antiquated and unorthodox to modern programmers, but it was a revelation for a young programming explorer like me. It allowed me to create loops, skip conditions, and organize my code in ways that, at the time, seemed magical.
However, over time and with more experience, I learned that abusing GOTO can lead to disorganized and hard-to-maintain code. Modern programming languages offer more sophisticated structures like for loops, conditional statements, and functions, which promote writing cleaner and more readable code.
Nevertheless, my first encounter with GOTO remains a precious memory, a symbol of my naive exploration into the world of early programming. And it's a memory that reminds me of the importance of ingenuity and curiosity in learning new things, even when it comes to ancient programming constructs.
Why today, using GOTO is discouraged
Using goto
is discouraged in many programming languages, including PHP, due to several reasons:
Readability: Code that heavily relies on
goto
statements can be difficult to understand, especially for developers unfamiliar with the codebase.goto
statements can lead to spaghetti code, where the execution flow is hard to follow.Debugging: Debugging code that uses
goto
statements can be challenging. When the program jumps around usinggoto
, it becomes harder to trace the flow of execution and track down bugs.Maintainability: Code that uses
goto
statements tends to be less maintainable. If you need to modify the code later, understanding and making changes can be more difficult and error-prone.Structured Programming:
goto
statements can lead to unstructured code that violates the principles of structured programming. Structured programming promotes using control structures like loops and conditionals to create well-organized, easy-to-understand code.Scoping Issues:
goto
has limitations related to scoping. Usinggoto
to jump into a different scope (e.g., into a loop or a conditional block) can cause issues and is generally considered bad practice.
While goto
can sometimes offer a way to break out of deeply nested loops or implement specific control flow patterns, it's often possible to achieve the same results using more structured constructs like for
, while
, foreach
, and if
statements. These constructs are more familiar to most developers and encourage writing cleaner, more maintainable code. Therefore, it's recommended to avoid using goto except in rare cases where its benefits outweigh its drawbacks, and even then, it should be used judiciously.
"Please Don't Try This at Home": an example with GOTO
Now, I will show you a conversion of a PHP code snippet that uses a while loop to read and display data from a CSV file. We will use the goto
statement to replicate the loop functionality in the final code. This demonstrates how the goto
statement was used instead of the more modern loop controls. You will see how the code is less readable, difficult to understand, and difficult to debug with the goto
usage.
I will use PHP, which provides the goto
statement.
I picked "Read and print the entire contents of a CSV file" example from the PHP documentation. The code uses for
and while
statements:
<?php
$row = 1;
if (($handle = fopen("118864.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "$num fields in line $row: " . PHP_EOL;
$row++;
for ($c = 0; $c < $num; $c++) {
echo " " . $data[$c] . PHP_EOL;
}
}
fclose($handle);
}
So, I think we are pretty familiar with the code above, using while
, and for.
Now let me show you the code where I will avoid using while
and for
and I will use goto
and labels:
<?php
start:
$row = 1;
if (($handle = fopen("118864.csv", "r")) === false) {
goto goodbye;
}
loop:
if (($data = fgetcsv($handle, separator:",")) === false) {
goto goodbye;
}
$num = count($data);
echo "$num fields in line $row: " . PHP_EOL;
$row++;
$c = 0;
loopLine:
if ($c >= $num) goto endLoopLine;
echo " => " . $data[$c] . PHP_EOL;
$c++;
goto loopLine;
endLoopLine:
goto loop;
closeFile:
fclose($handle);
goodbye:
echo "Goodbye";
In the provided code, labels like start
, loop
, and loopLine
are used as markers for specific points in the code's execution flow. Here's an explanation of their usage:
start
: This label marks the beginning of the code execution. It's where the program starts its execution when it's run.loop
: This label marks the start of a loop for parsing the CSV file, line by line. It's used to indicate the point where the program should return to after completing each iteration of the loop.loopLine
: This label marks the inner loop within the main loop. It's used to iterate over each file line, for parsing the fields in the current line.endLoopLine
: This label marks the end of the inner loop. It's where the program jumps to after iterating over all lines in the file.closeFile
: This label is not used through thegoto
in the provided code. However, it could be utilized to mark the point where the file handle is closed after processing.goodbye
: This label marks the end of the program's execution. It's where the program goes if it encounters an error or reaches the end of its main logic. In this case, it prints "Goodbye".
These labels and the goto
statements allow for a non-linear flow of control in the code. However, it's important to note that excessive use of goto
statements and labels can make the code harder to understand and maintain. Again, it's generally considered good practice to use more structured constructs like loops (for
, while
, foreach
) and conditional statements (if
, else
) to achieve the desired control flow whenever possible.
References
- The example for "Read and print the entire contents of a CSV file" from the PHP documentation: https://www.php.net/manual/en/function.fgetcsv.php#refsect1-function.fgetcsv-examples
- The
goto
control structures in PHP: https://www.php.net/manual/en/control-structures.goto.php
Top comments (6)
Interesting discussion, and code illustration, of what seems to generally be regarded as a taboo topic.
Not sure why this is the case. Its use (unconditional branching) is an integral part of assembly language programming. Older legacy code (COBOL, not Java, shells like DOS Batch and DCL) is replete with its use.
I would say professional programmers should be as knowledgeable of it, and its uses, as they should of other language constructs and idioms. They then use this knowledge and their professional judgement, to craft their code.
Finally, I would recommend that this line:
should, for added clarity, be changed to:
Why ? You have an open file handle that will, eventually, need to be closed.
In the example, since the program ends after the final statement, cleanup (including the closing of open files handles) occurs, so is not strictly necessary.
However, if the code were part of a larger construct, correctly performing each step not only adds clarity, but robustness as well.
Thank you for you effort.
Thanks for the feeedback @ajborla !
Appreciated.
I wanted to write a short article about this approach to share a different approach to different awareness with developers and to make them aware of a different flow from the classic loops.
Then, I added my own personal observations about the complexity of this approach. Undoubtedly, the use of goto and label can be effective for someone and in some situations. Everyone makes their own considerations.
The readability considerations are also personal and a consequence of my current style. I remember when I worked with assembly in the past, the goto approach helped me a lot in understanding assembly (but also cobol itself)
I will update the code according to your directions, I agree.
Thank you very much
Wow that example is disorientating!
I only understood it after reading the php documentation.
The part I was stuck on, was the loop. My mind broke on the logic how it got from start to loop.
Php just runs line after line. But the named segments just threw me off.
For people who want to follow the flow:
start -> loop -> loopline (X times) -> endloopline -> loop -> goodbye
It never goes to the closeFile segement?
Thank you @xwero for your valuable feedback!
The article mainly focuses on the approach; the example is on the side, but thanks to your feedback, I can explain the
goto
command, labels, and execution flow.The
closeFile
label (as mentioned in the article) is not used through thegoto
in the provided code. However, it could be utilized to mark the point where the file handle is closed after processing.But I will change the code to add a
goto
in case of an exception and use thecloseFile
label.Thank you again. I appreciate your feedback
Kind of funny that in assembly language, GOTOs are effectively everywhere π
Wow! I thought
goto
is removed from every modern language!