Direct response
The reason why people say to avoid the goto
is readability. It would be to facilitate the understanding of the code, so the programmer does not get lost in what the code does. The goto
in itself does not cause any problem.
The goto
still exists because it is still useful. It exists because most language creators are pragmatic.
Where the myth came from?
Basically, the "guilty" is the article "go to statement considered Harmful" by Edsger W. Dijkstra. More precisely from his editor, who chose a very flashy title. Then all the people who talk about what they don’t know perpetuated the myth.
Of course the article shows a situation where the goto
does not need to be used. But it does not say that the goto
should not exist. In fact the article only tries to sell the idea of structured programming.
In the past programs were understood a lot by their flow, be they in Assembly, or in the first high-level languages. Programming structured and modularized emerged shortly after to revolutionize programming once again. This way the programs would be understood by their structure and not by their flow. This really proved to be a huge facilitator for understanding the programs, which were getting bigger and bigger.
Like the cordless phone used to be people’s favorite joke they started to repeat that the goto
fried his brain or made the computer pop bubbles.
What is a Goto?
By the way people talk it seems that word/expression goto
is the problem. A break
or continue
can be considered goto
? And a break label
? A return
? And what will you say to throw
?
The throw
seems to be one of the most beloved commands of programmers nowadays in most languages. And it can be considered the worst kind of goto
. It is difficult to create a control structure as unpredictable as the throw
, but I don’t see people speaking ill of it. In fact the treatment of exceptions seems to be one of the most abused resources in programming this century. It’s okay that the abuse occurs more because of the catch
where nothing useful can be done, but the catch
is just the label of the deviation caused by goto
. I talk about it in several posts but it seems that the people who most need to read these things only have time to post their little code problems. See It is good practice to make an exception in such cases?, best way to deal with exceptions and exception.
Although I find radicalism that seeks problems rather than solutions, I find it more coherent who thinks that any form of goto
is bad. Prejudice with the word is that we can not accept.
Of course some implementations of goto
, Especially the older ones, they may not be ideal, let you do some crazy stuff that doesn’t help anyone. But of course it is not the problem of the concept, but of the implementation.
He shouldn’t exist?
while x < 10
print x
x++
end
Is the same as
while: if x >= 10 goto end
print x
x++
goto while
end:
Of course, the first way reduces the size of the code by having a syntax sugar. But it’s harder to follow the second example than the first?
The goto
by itself does not cause problem or even legibility. The misuse of it can cause difficulties to maintain the program.
It might look like I’m advocating the use of goto
. Far from it, you should try to avoid its use to the maximum, but not at any cost. The programming based on goto
certainly it is quite problematic, but the parsimonious use of the resource by those who understand its functioning and know the difficulties it can impose on their program is not problematic.
It is ironic to see legibility advocates provide unreadable codes just to meet the "rule" that a goto
should not be used. There are those who think that flags are better than wearing a goto
. It may be in some case, but not for everything. Saving and controlling a variable’s state to avoid the goto
is a typical case of increasing complexity in the name of the rule.
There are cases that the goto
facilitates readability, the main ones have already been demonstrated in the other answers. A very useful case is to avoid the use of multiple exit points (return
) as demonstrated in a reply of mine.
I learned to code using a language that basically only had goto
. I used for many years a language that the closest to the goto
was just the break
and continue
. Today I use languages that do not encourage their use but allow limited use. This is the point. I can’t remember the last time I used the infamous one, but I like to know I can use it when I need it.
I hate languages that want to protect the programmer by not allowing to do what can be useful. You just force the use of more complex structures that will be well done, as far as possible, by good programmers, and will be very badly done by other programmers. The absence of goto
in the language limits good programmers and does not solve any real problems.
- Languages that do not have
goto
complicate the lives of those who need to create code generators for these target languages.
- Not having
goto
promotes non-standard complicated constructions, especially in the creation of state machines.
- Can reduce the ease for really needed optimizations on codes that need to boot maximum performance.
- The lack of
goto
increases cyclomatic complexity in many cases.
It’s a shame that a language like Javascript, which is so used as target of other, don’t have a goto
native.
Some languages correctly limit or may limit what the goto
can do:
- Certainly the
goto
should not skip important parts of the code;
- should not be allowed to enter within a scope forcibly;
- some people think I shouldn’t allow the flow to go back.
The goto
can be used in a structured way. Donald Knuth knows this. Who am I to contest it. It is not the use of goto
opposed to structured programming. Abuse of it yes.
Another that gives good tips on how to use the goto
properly is Stece Mcconnel at Code Complete.
Perhaps the most complete explanation, not necessarily the best, on the subject is in that article.
No one is obliged to agree with everything I or these people have written. I do not agree with everything. But there are facts and good observations.
Avoid the goto
can be as damaging as using it. Overall a goto
is worth more than violating the DRY.
What language are we talking about?
AP cites the language C. This is a language that needs a lot of goto
to clean resources, release memory, close operations. Someone may complain that this is a language problem. But he’s still useful and that’s what matters.
There are languages that have no form of goto
and then they did. Because they saw usefulness.
Every language has a need. Some need more than others, but all can benefit from it to a greater or lesser degree.
Without knowing what language we are talking about, we can only say that the goto
is useful yes. Knowing the language, we can say more precisely where it is useful.
I am not going to talk about languages already spoken in other responses, and obviously I am not going to talk about languages that I do not understand.
Legitimate uses in C#
According to the Microsoft reference for the command, some legitimate uses are:
class SwitchTest {
static void Main() {
Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
Console.Write("Please enter your selection: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int cost = 0;
switch (n) {
case 1:
cost += 25;
break;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
default:
Console.WriteLine("Invalid selection.");
break;
}
if (cost != 0) Console.WriteLine("Please insert {0} cents.", cost);
Console.ReadKey();
}
}
A common case in C# is to put the goto case <próximo caso>
. He is a form of Fall through, since C# does not have this automatic feature, i.e., a block case
needs to end with break
or goto
. Some people think C# should have the Fall through automatic to reduce a code size. Others say this causes bugs.
Another way:
public class GotoTest1 {
static void Main() {
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
array[i, j] = (++count).ToString();
Console.Write("Enter the number to search for: ");
string myNumber = Console.ReadLine();
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (array[i, j].Equals(myNumber)) goto Found;
}
}
Console.WriteLine("The number {0} was not found.", myNumber);
goto Finish;
Found:
Console.WriteLine("The number {0} is found.", myNumber);
Finish:
Console.WriteLine("End of search.");
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
In some languages that do not have the reserved word goto
this can be obtained by break label
. But only because you don’t have the floor goto
it ceases to be problem? Skip more than one level of a loop nested is something that command helps. Attempts to avoid it, in general, lead to worse code.
It is likely that language would be less criticized if it created a break label
to solve these two cases. This shows that hatred of the resource is irrational. In any case, other ways would still be prohibited and is an undesirable limitation.
A desirable and existing limitation in language is the prohibition of label be in a more internal scope than goto
or in another scope. There’s no way to get inside a loop through the goto
, for example. Getting out of it is no problem, because it is the goto
which is more internal, and not the label. This is not possible:
var a = 1;
var s = "";
if (a == 1) {
s = "1";
goto label1;
} else if (a >= 2) {
s = "2";
goto label1;
} else {
label1:
s += "3";
}
Obviously exit a method with goto
is not allowed.
A label can’t be one last statement (yes, the label is a statement) of a method. You need to have something after it even if it’s just a return
or a statement emptiness (;
).
Within a finally
there can be no goto
.
The finally
will be executed even if a goto
try to avoid it. The finally
has priority and the * label* of a goto
will only receive the program flow when all finally
s involved are executed.
try {
...
goto label1;
} finally {
CloseAll();
}
label1:
FazAlgo();
In this case the CloseAll()
will be executed before the FazAlgo()
undoubtedly.
A example found in Code Review where the answer you accept is worse than the one you use goto
:
string errorMessage;
while(!TryTableFill(myDataTable, out errorMessage)) {
DialogResult result = MessageBox.Show("Can't load data:\n" + errorMessage, "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
if(result != DialogResult.Retry)
break;
}
private boolean TryTableFill(myDataTable, out string errorMessage) {
errorMessage = string.Empty;
try {
oleDbDataAdapter1.Fill(myDataTable);
return true;
} catch (Exception ex) {
errorMessage = ex.Message;
return false;
}
}
Apparently (not for me) it’s better than:
start:
try {
oleDbDataAdapter1.Fill(myDataTable);
} catch (Exception ex) {
DialogResult res = MessageBox.Show("Can't load data:\n" + ex.Message, "Error",
MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
if (res == DialogResult.Retry)
goto start;
}
Swears to avoid the goto
in the code below left the code more readable?
var tryAgain = true;
while (tryAgain) {
try {
...
tryAgain = false;
} catch (...) {
tryAgain = true
}
}
With goto
:
tryAgain:
try {
...
} catch (...) {
goto tryAgain;
}
I’ve seen cases where the programmer put a loop and at least 2 unconditional deviations (any combination of break
and continue
) to avoid a simple, innocent and readable goto
.
Example of misuse
var retVal = false;
if(cond1)
goto exit;
if(cond2)
goto exit;
if(cond3)
goto exit;
retVal = true;
exit:
return retVal;
May be replaced by:
return !(cond1 || cond2 || cond3);
Try to use the goto
to express its intention and not as a mechanism. In this case the intention did not need to goto
nor of a complex structure. The problem here is neither the goto
. See the version of it without the use of the devil command and that remains bad:
if(cond1)
return true;
if(cond2)
return true;
if(cond3)
return true;
return false;
Completion
Bad programmers will produce bad code, no matter if you use it goto
or not. It is unfortunate to see cases of goto
where there is a better construction. But it’s even worse to see bad code because a blind rule was used.
The goto
can be useful for:
- Make code easier to read.
- Reduce the code size.
- Avoid repetition of code.
- Facilitate automatically generated code.
- Get out of loops nested.
- Manipulate state machines.
- Ensure a clean exit from a routine.
Diet tells you to eat less and with more quality to take care of your health, does not tell you not to eat. Take care of your health and use a little, a little bit of goto
, whenever he benefits more than hinder.
I put in the Github for future reference.
One more example in question here.
In my view, one of the main reasons is that using GOTO too often confuses the code. If you take a look at the discussions on this subject in the English OS, maybe this will help you understand. http://stackoverflow.com/questions/11906056/goto-is-this-bad http://stackoverflow.com/questions/46586/goto-still-considered-harmful
– Giovani
I’m just waiting for a question about the usefulness of
COMEFROM
.– Guilherme Bernal
Four answers so far and no one has quoted Dijkstra and his famous "Go To Statement Considered Harmful"?
– Piovezan
In my case, I will answer the reason why I do not quote him: I do not want my answer to look like "an important guy spoke then is spoken". It is important to understand on your own.
– marcus
Moreover, contradicting me and now using a quote, just for humor, "Arrogance in computer science is measured in nano-Dijkstras" - Alan Kay :-)
– marcus
The goal of citing it is precisely with a critical stance, as @bigown did. Do not accept because "an important guy quoted" but include the quote for historical value.
– Piovezan
We are in 1980 ?! It has been more than proven that it is a bad programming practice , modern languages no longer have the syntax ... I respect your right to debate but frankly regret the subject.
– Motta