The original context in which Dijkstra wrote that was very different; he was primarily referring to old versions of Fortran and BASIC, where gotos where more or less the only (or the predominant) form of branching. In other words, something like
if (foo() || bar())
xyzzy();
else
idkfa();
would have often been written something like
100 F = FOO()
200 B = BAR()
300 IF F OR B
400 GOTO 4840
500 ELSE
600 GOTO 8000
700 ....
and whatever was happening at 4840 would GOTO back to 700 (with predictable catastrophic results if anything before 700 changed) and so on.
Local use of goto in the context of e.g. bailing out of an ini function if something failed early in the initialization sequence is useful and not frowned upon by people whose daily work consists of something other than writing coding standards. There are a few (well-meant!) exceptions that have to do with e.g. static analysis, but those tend not be so important outside the field of high-reliability systems.
if (foo() || bar()) xyzzy(); else idkfa();
would have often been written something like
100 F = FOO() 200 B = BAR() 300 IF F OR B 400 GOTO 4840 500 ELSE 600 GOTO 8000 700 ....
and whatever was happening at 4840 would GOTO back to 700 (with predictable catastrophic results if anything before 700 changed) and so on.
Local use of goto in the context of e.g. bailing out of an ini function if something failed early in the initialization sequence is useful and not frowned upon by people whose daily work consists of something other than writing coding standards. There are a few (well-meant!) exceptions that have to do with e.g. static analysis, but those tend not be so important outside the field of high-reliability systems.