As I already wrote some times but it never hurt to repeat it, IMO the perfect example why GOTO should be used in PB programs is another.
It's the ability of leave a procedure while keeping a single exit point where you do the cleanup of the resources allocated along the body of the procedure up to the point of a failure that is forcing you to leave.
All this resulting in clean code readable from top to bottom with the assumption that no error will happen, in a way similar to languages supporting exceptions handling, without nested IF RETURNVALUE using dubious vars to keep tracks of the current error state or multiple breaks or fake loops or other atrocities.
Someone else already explained it with some code so I don't have to do it myself:
http://www.cprogramming.com/tutorial/goto.html
And using some macros you can even make it similar (cosmetically) to proper exception handling and so pleasing to see and easy to understand and follow.
All the advantages lost by avoiding this approach are probably the first and major reason why so much code written by PB coders has faulty, incomplete or totally missing error checking. Because when the complexity of a single procedure grows it become tedious work, adds distracting redundant noise when reading back code, it is extremely error prone, and it is difficult to write.
Another good use is to leave deep nested structured code, as explained also in the K&R, but it comes a distant second IMO.
Some excerpt from "Structured programming with goto statements", a 1974 article from Knuth.
I suggest its reading to everyone using PB, it's very nice and thought provoking.
Before starting to laugh, consider PB at its core it's certainly not a language of the second millenium, but more of the '70s.
Such checks on the validity of
data are very important, especially in soft-
ware, and it seems to be the one class of go
to's that still is considered ugly but neces-
sary by today's leading reformers.
[...]
Sometimes it is necessary to exit from
several levels of control, cutting across code
that may even have been written by other
programmers; and the most graceful way to
do this is a direct approach with a go to or
its equivalent. Then the intermediate levels
of the program can be written under the
assumption that nothing will go wrong.
Sound familiar ?
Event Indicators
The best such language feature I know has
recently been proposed by C. T. Zahn.
[...]
The essential novelty
in his approach is to introduce a new quan-
tity into programming languages, called an
event indicator (not to be confused with
concepts from PL/I or SIMSC~IPT). My
current preference is to write his event-
driven construct in the following two general
forms.
[...code follows...]
It is important to emphasize that the first
line of the construct merely declares the
event indicator names, and that event
indicators are not conditions which are being
tested continually; (event) statements are
simply transfers of control which the com-
piler can treat very efficiently. Thus, in
Example 5e the statement "leaf replaced"
is essentially a go to which jumps out of
the loop.
[...]
Of course, event indicators are not the only
decent alternatives to go to statements
that have been proposed. Many authors
have suggested language features which
provide roughly equivalent facilities, but
which are expressed in terms of exit, jump-
out, break, or leave statements. Kosaraju
has proved that such statements are
sufficient to express all programs without
go to's and without any extra computation,
but only if an exit from arbitrarily many
levels of control is permitted.
Until then, Break 37 or goto.
I'll leave to you to guess how those "event indicators" evolved in many contemporary languages.