Is using goto here really so bad?
In March 1968, Dijkstra sent a letter to Communications of the ACM which was published under the title Go To Statement Considered Harmful. It is an interesting read, and part of programmer lore.
The argument against GOTO presented in this letter has to do with how programmers build a mental model to track the progress of code execution. Dijkstra argues that such a mental model is important, because the value of variables is meaningful only relative to the execution progress. For example, when our program is counting the number of times an event occurs, there is always an in-between moment where N events have occurred, but the variable keeping track of it has not yet been incremented and is still at N-1.
He goes through these steps in his reasoning against GOTO:
First consider a very simple language without procedures, loops or GOTO. In such a language, the programmer can mentally track execution by imagining an execution pointer advancing from the start of the file to the end. A single index (i.e. the line number) suffices to model execution progress.
Now we add procedures to the language. The execution progress can no longer be tracked by a single index, as it might be inside a procedure. We also have to keep track from which line the procedure was called. Also, procedures can be called from other procedures. Therefore, we model execution progress as a sequence of indices. (In real life, programmers call such a sequence a "stack trace".)
Now we add loops to the language. For each line in our stack trace that is inside a loop body, we need to add another type of index to model execution progress: the repetition count.
Now we add GOTO. Dijkstra argues that with unbridled use of GOTO, our ability to track execution progress now breaks down. We can still track execution progress with an "execution clock" by saying "now we're executing the 152nd statement". However, this is not really helpful to establish the context that is necessary to interpret the values of variables.
As long as we only use GOTO statements to build simple loops, you can argue that the situation is equivalent to point (3), and there is no problem. But in that case you can just use the loop constructs. Better to just keep GOTO out of your code, so that you don't slip into the situation described in point (4).