I, for one, think of GOTOs as an essential part of my coding toolkit. For many, many things, they just make sense.
Where do you see me use them a ton??
In SUB/FUNCTIONs, as a means to clean up/restore settings before exiting.
For example, I might have a routine which tosses colored text on the screen..
FUNCTION ColoredTextAtPos (foreground, background, font, text$, xpos, ypos)
Now, the first things I want to get is:
D =_DEST: S =_SOURCE
F =_FONT
Oldx = POS(0): OldY = LOC
DC =_DEFAULTCOLOR: BG = _BACKGROUNDCOLOR
All the current settings to affect my screen...
Then I do my main process, which might have multiple exit points... If text$ = "", settings for SCREEN 0, 256 color graphic modes, and 32-bit color graphic modes, if the font is monospaced, unicode, or not....
Now some folks might sit down and scheme out some method to include/exclude all those various settings, but I tend to find it easiest to just handle them linearly one by one, myself.
IF text$ = "" THEN GOTO exit_point
IF xpos < 0 OR ypos < 0 THEN GOTO exit_point
I can't always just EXIT FUNCTION, as I may need to reset those initial values I captured, so a label called exit_point makes perfect sense a few lines before the END FUNCTION, so I can do those value resets afterwards.
It's not confusing. It's not spaghetti code. Nobody scratches their head reading it, and has a hard time understanding it. In fact, I'd argue that with proper use of a descriptive label, like exit_point above, that it's *more* readable and self-documenting than many other ways you might write the same code.
GOTO isn't inherently bad. It's just bad when it's used improperly, and then it's *really* bad.