I refer you to David Tribble's recent (2005) annotated retrospective of E. W. Dijkstra's famous 1968 letter to the ACM entitled "Go To Statement Considered Harmful". I strongly recommend that you read it in its entirety. It puts the whole issue in historical context. It avoids dogma on either side of the debate. And it comes to a rational. balanced conclusion about the whole issue.
Personally, my first heavily-used programming language was Fortran IV, in which a great majority of the code DEPENDS on the use of the "GOTO statement". Enormous amounts of my team's time and effort went into debugging spaghetti code.
As Fortran 77 and C began to dominate the landscape, the situation improved a great deal. Fairly often I was able to resolve longstanding bugs in Fortran IV code simply by rewriting it to use structured loops and conditionals. In many of those cases the bug became obvious merely by going through the thought process of converting goto-laden logic to structured logic. The conclusion to me was that structured logic just fits the human brain better than jump-and-branch logic.
Which brings us to now. For the past 10 years I have worked almost exclusively in Java, which has no goto construct whatsoever. I do not miss it at all.
-------------
As to your specific question, my return question is "why?" Function names document usage and, well used, can make the purpose of a code block crystal clear. Goto labels can document usage, but inputs and outputs of a code goto code block are a mystery.
Sure, you can do it. And you could even rig up a stack mechanism of your own so that you can remove your "never need to return" proviso. But why oh why would you want to?
"Would this be in any way worse..."? Yes, code readability would suffer considerably.
"...there are times it might be better." Can you give us an example? I can think of examples where it might be "not so bad", but none where it is "better".
"As long as you are not breaking into anything that might get complicated..." Well, back in the day that was exactly the problem. People used goto statements to do all sorts of complicated overlapping-but-not-nested looping/skipping constructs. However, in fairly simple cases, spread over no more than a few lines, you could get some fairly elegant looking (though still hard to decipher) code. For example, there is this from the paper I referenced:
int parse()
{
Token tok;
reading:
tok = gettoken();
if (tok == END) return ACCEPT;
shifting:
if (shift(tok)) goto reading;
reducing:
if (reduce(tok)) goto shifting;
return ERROR;
}
I still like the following structured equivalent better, because it makes the nature of the looping a lot more obvious:
int parse()
{
Token tok;
while (true) {
tok = gettoken();
if (tok == END) return ACCEPT;
while (true) {
if (shift(tok)) break;
if (!reduced(tok)) return ERROR;
}
}
}
But the overall code is small and simple enough that I would not really be bothered by the unstructured code block.
In my experience, though, REAL goto-laden code is almost never that short and elegant. The label is usually somewhere between dozens and hundreds of lines from the goto and there is no easy way to tell which direction to go just by looking at the goto. Perhaps if there were two different statements: goback and goforward, it would not be as bad, but, alas, in real languages there aren't.