goto
wird fast allgemein abgeraten. Lohnt es sich jemals, diese Aussage zu verwenden?
goto
programming-practices
Casebash
quelle
quelle
goto
ist das, was die CPU letztendlich macht, aber es funktioniert nicht gut mit dem, was Menschen verstehen und abstrahieren müssen, weil es keine Markierung am Zielende gibt. Vergleiche mit IntercalCOMEFROM
.goto
nicht erforderlich. Es ist nur die rationalste Art, sie in den imperativen Sprachen umzusetzen, da es der Semantik des Staatsübergangs am nächsten kommt. Und sein Ziel kann ziemlich weit von der Quelle entfernt sein, es wird die Lesbarkeit nicht behindern. Mein Lieblingsbeispiel für einen solchen Code ist DE Knuths Implementierung des Abenteuerspiels.Antworten:
Dies wurde im Zusammenhang mit Stack Overflow mehrmals diskutiert, und Chris Gillum fasste die möglichen Verwendungen von
goto
:Ich würde argumentieren, wie viele andere argumentieren würden, dass in all diesen Fällen die Verwendung von
goto
als Mittel verwendet wird, um aus einer Ecke herauszukommen, in die man sich selbst codiert hat, und im Allgemeinen ein Symptom für Code ist, der umgestaltet werden könnte.quelle
finally
Blöcke in modernen Sprachen gelöst, und das zweite Problem wird durch mitbreak
s bezeichnete gelöst . Wenn Sie jedoch mit C nicht weiterkommen,goto
ist dies so ziemlich die einzige Möglichkeit, diese Probleme auf elegante Weise zu lösen.finally
ist nur unter diesen Bedingungen gültig. Es gibt sehr seltene, aber gültige Situationen, in denen ein Goto der richtige Weg ist.break 3
oderbreak myLabel
undgoto myLabel
. Oh, das ist richtig, nur das Schlüsselwort. Wenn Sie verwendenbreak
,continue
oder einige ähnliche Keyword Sie sind infact mit einemgoto
(Wenn Sie verwendenfor, while, foreach, do/loop
Sie einen bedingten goto verwenden.)Übergeordnete Kontrollflusskonstrukte tendieren dazu, Konzepten in der Problemdomäne zu entsprechen. Ein if / else ist eine Entscheidung, die auf einer bestimmten Bedingung basiert. Eine Schleife fordert Sie auf, einige Aktionen wiederholt auszuführen. Sogar eine break-Anweisung besagt, "wir haben das wiederholt gemacht, aber jetzt müssen wir aufhören".
Eine goto-Anweisung entspricht dagegen eher einem Konzept im laufenden Programm, nicht in der Problemdomäne. Es heißt, die Ausführung an einer bestimmten Stelle im Programm fortzusetzen . Jemand, der den Code liest, muss ableiten, was dies in Bezug auf die Problemdomäne bedeutet.
Natürlich können alle übergeordneten Konstrukte in Form von gotos und einfachen bedingten Verzweigungen definiert werden. Das heißt nicht, dass sie nur verkleidet sind. Betrachten Sie sie als eingeschränkte GOTOS - und es sind die Einschränkungen, die sie nützlich machen. Eine break-Anweisung wird als Sprung an das Ende der einschließenden Schleife implementiert, aber es ist besser, sie als Operation für die gesamte Schleife zu betrachten.
Wenn alles andere gleich ist, ist Code, dessen Struktur die der Problemdomäne widerspiegelt, in der Regel leichter zu lesen und zu warten.
Es gibt keine Fälle, in denen eine goto-Anweisung unbedingt erforderlich ist (es gibt einen entsprechenden Satz ), aber es gibt Fälle, in denen dies die am wenigsten schlechte Lösung sein kann. Diese Fälle variieren von Sprache zu Sprache, je nachdem, welche übergeordneten Konstrukte die Sprache unterstützt.
In C glaube ich zum Beispiel, dass es drei grundlegende Szenarien gibt, in denen ein goto angemessen ist.
Andererseits kann eine explizite Zustandsmaschine auch mit einer switch-Anweisung innerhalb einer Schleife implementiert werden. Dies hat den Vorteil, dass jeder Zustand an der gleichen Stelle im Code beginnt, was beispielsweise beim Debuggen hilfreich sein kann.
Die Hauptverwendung eines goto in einer einigermaßen modernen Sprache (eine, die if / else und Schleifen unterstützt) besteht darin, ein Kontrollflusskonstrukt zu simulieren, das in der Sprache fehlt.
quelle
goto
. SSSMs sind oft gute Strukturen, da sie den SM-Status vom Ausführungskonstrukt trennen, aber "gotos" nicht wirklich eliminieren.Das hängt sicher von der Programmiersprache ab. Der Hauptgrund
goto
für die Kontroverse ist, dass der Compiler Sie zu großzügig einsetzen lässt. Probleme können beispielsweise auftreten, wenn Sie so verwendengoto
können, dass Sie jetzt auf eine nicht initialisierte Variable zugreifen können, oder noch schlimmer , wenn Sie in eine andere Methode springen und mit dem Aufrufstapel herumspielen. Es sollte in der Verantwortung des Compilers liegen, unsinnigen Kontrollfluss zu verbieten.Java hat versucht, dieses Problem zu "lösen", indem es dies
goto
vollständig untersagte . Mit Java können Sie jedochreturn
innerhalb einesfinally
Blocks eine Ausnahme verwenden, die versehentlich verschluckt wird. Das gleiche Problem besteht immer noch: Der Compiler erledigt seine Arbeit nicht. Das Entfernengoto
aus der Sprache hat das Problem nicht behoben.In C #,
goto
ist so sicher wiebreak
,continue
,try/catch/finally
undreturn
. Sie können keine nicht initialisierten Variablen verwenden, Sie können nicht aus einem finally-Block usw. herausspringen. Der Compiler beschwert sich. Dies liegt daran, dass es das eigentliche Problem löst , das wie gesagt unsinniger Kontrollfluss ist.goto
Bricht die Analyse bestimmter Zuordnungen und andere sinnvolle Compilerprüfungen nicht auf magische Weise ab.quelle
goto
nicht böse ist? Wenn ja, ist das für jede routinemäßig verwendete moderne Sprache mit einemgoto
Konstrukt der Fall , nicht nur für C # ...Ja. Wenn Ihre Schleifen mehrere Ebenen tief verschachtelt sind,
goto
ist dies die einzige Möglichkeit, elegant aus einer inneren Schleife auszubrechen. Die andere Option besteht darin, ein Flag zu setzen und aus jeder Schleife auszubrechen, wenn dieses Flag eine Bedingung erfüllt. Das ist wirklich hässlich und ziemlich fehleranfällig. In diesen Fällengoto
ist es einfach besser.Natürlich macht Javas beschriftete
break
Anweisung dasselbe, aber ohne dass Sie zu einem beliebigen Punkt im Code springen können, wodurch das Problem ordentlich gelöst wird, ohne dass die Dinge zugelassen werden, die dasgoto
Böse machen .quelle
Do
Schleife. Warum? Weil ich die eine Schleife, die eine tiefe Pause braucht, in eineDo
Schleife und Typ ändern kannExit Do
und es keine gibtGoTo
. Verschachtelte Schleifen passieren die ganze Zeit. Das Brechen der Stapel geschieht in einigen Prozent der Fälle.Der größte Teil der Entmutigung kommt von einer Art "Religion", die von Gott Djikstra geschaffen wurde und die in den frühen 60er Jahren zwang, über ihre wahllose Macht zu sprechen, um:
Dies hat nichts mehr mit der
goto
Aussage der modernen Sprachen zu tun , deren Existenz lediglich die Schaffung anderer als der von der Sprache bereitgestellten Codestrukturen unterstützen soll.Insbesondere ist der erste Hauptpunkt oben nicht mehr erlaubt und der zweite wird gereinigt (wenn Sie
goto
aus einem Block heraus sind, wird der Stapel richtig abgewickelt und alle richtigen Destruktoren aufgerufen).Sie können sich auf diese Antwort beziehen , um eine Vorstellung davon zu bekommen, wie unlesbar Code sein kann, der goto nicht verwendet. Das Problem liegt nicht bei sich selbst, sondern in der schlechten Verwendung.
Ich kann ein ganzes Programm , ohne schreiben
if
, einfachfor
. Natürlich ist es nicht gut lesbar, sieht ungeschickt und unnötig kompliziert aus.Das Problem ist aber nicht
for
. Da ich bin.Dinge wie
break
,continue
,throw
,bool needed=true; while(needed) {...}
usw. unter Hinweis darauf , mehr als Maskeradegoto
von den Säbeln der Djikstrarian Eiferer zu entkommen weg, dass -50 Jahre nach der Erfindung der modernen laguages- noch ihre Gefangene wollen. Sie vergaßen, wovon Djikstra sprach, sie erinnerten sich nur an den Titel seiner Notiz (GOTO wurde als schädlich eingestuft, und es war nicht einmal sein eigener Titel: Er wurde vom Herausgeber geändert) und beschuldigten und schlugen, schlugen und schlugen jedes Konstrukt, das diese 4 hatte Buchstabe in Reihenfolge gebracht.Es ist 2011: Es ist Zeit zu verstehen, dass Djikstra
goto
sich nicht mit derGOTO
Aussage auseinandersetzen muss, die ihn überzeugt hat.quelle
break n
in C ++ nicht verfügbargoto escape
, selbst wennescape
es nicht erforderlich ist, nur aus der n-ple-Schleife herauszukommen.Das seltsame Hin- und Her, solange es sich um eine lokale Funktion handelt, beeinträchtigt die Lesbarkeit nur selten erheblich. Oft wird es dadurch verbessert, dass darauf hingewiesen wird, dass in diesem Code etwas Ungewöhnliches vor sich geht, das die Verwendung einer etwas ungewöhnlichen Kontrollstruktur erfordert.
Wenn (lokale) gotos die Lesbarkeit erheblich beeinträchtigen, ist dies normalerweise ein Zeichen dafür, dass die Funktion, die das goto enthält, zu komplex geworden ist.
Das letzte, was ich in einen C-Code geschrieben habe, war, ein Paar ineinandergreifender Schleifen zu erstellen. Es passt nicht in die normale Definition von "akzeptabler" Verwendung, aber die Funktion wurde dadurch deutlich kleiner und klarer. Um dies zu vermeiden, wäre eine besonders unordentliche Verletzung von DRY erforderlich gewesen.
quelle
Ich denke, diese ganze Angelegenheit war ein Fall, in dem der falsche Baum angebellt wurde.
GOTO als solches scheint mir kein Problem zu sein, aber es ist sehr oft ein Symptom einer tatsächlichen Sünde: Spaghetti-Code.
Wenn das GOTO eine größere Überschneidung von Flusskontrolllinien verursacht, ist es schlecht, Punkt. Wenn es keine Flusskontrolllinien kreuzt, ist es harmlos. In der Grauzone dazwischen haben wir Dinge wie Loop-Rettungsaktionen. Es gibt immer noch einige Sprachen, die keine Konstrukte hinzugefügt haben, die alle legitimen Graufälle abdecken.
Der einzige Fall, in dem ich es in vielen Jahren tatsächlich verwendet habe, ist der Fall der Schleife, in der sich der Entscheidungspunkt in der Mitte der Schleife befindet. Sie haben entweder doppelten Code, eine Flagge oder ein GOTO. Ich finde die GOTO-Lösung die beste der drei. Es gibt hier kein Überkreuzen von Strömungskontrolllinien, es ist harmlos.
quelle
goto
s, die in eine Schleife springen (wenn die Sprache dies zulässt; seit dem anderen Fall wird gesprungen aus der Schleife in der Mitte, ist in der Regel ohne trivialgoto
).goto
als Schreien der Steuerungsablauf hier nicht passt NORMAL structured-PROGRAMMIER PATTERNS . Da Kontrollabläufe, die zu strukturierten Programmiermustern passen, einfacher zu überlegen sind als solche, die dies nicht tun, sollte man versuchen, solche Muster zu verwenden, wenn dies möglich ist. Wenn Code zu solchen Mustern passt, sollte man nicht schreien, dass dies nicht der Fall ist. Auf der anderen Seite ist es in Fällen, in denen Code wirklich nicht zu solchen Mustern passt, besser, darüber zu schreien, als vorzutäuschen, dass der Code passt, wenn dies wirklich nicht der Fall ist.Ja, das goto kann verwendet werden, um die Erfahrung des Entwicklers zu verbessern : http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Wie bei jedem leistungsfähigen Tool (Zeiger, Mehrfachvererbung usw.) muss man jedoch diszipliniert damit umgehen. Das in dem Link bereitgestellte Beispiel verwendet PHP, wodurch die Verwendung des goto-Konstrukts auf dieselbe Funktion / Methode beschränkt wird und das Springen in einen neuen Steuerblock (z. B. Schleife, switch-Anweisung usw.) deaktiviert wird.
quelle
Kommt auf die Sprache an. Es wird zum Beispiel immer noch häufig in der Cobol-Programmierung verwendet. Ich habe auch an einem Barionet 50-Gerät gearbeitet, dessen Firmware-Programmiersprache ein früher BASIC-Dialekt ist, der natürlich die Verwendung von Goto erfordert.
quelle
Ich würde nein sagen. Wenn Sie die Notwendigkeit finden, GOTO zu verwenden, müssen Sie den Code wahrscheinlich neu gestalten.
quelle
goto
Dies kann nützlich sein, wenn Sie älteren Assembler-Code nach C portieren. In erster Linie kann eine anweisungsweise Konvertierung nach Cgoto
als Ersatz für diebranch
Anweisung des Assemblers eine sehr schnelle Portierung ermöglichen.quelle
Ich würde nicht argumentieren. Sie sollten immer durch ein Tool ersetzt werden, das spezifischer für das zu lösende Problem ist (es sei denn, es ist in Ihrer Sprache nicht verfügbar). Beispielsweise lösen break-Anweisungen und -Ausnahmen Probleme, die zuvor durch Schleifen-Escape- und Fehlerbehandlung behoben wurden.
quelle
goto
in diesen Sprachen normalerweise nicht vorhanden sind.goto
, in denen die Problemdomänensemantik am nächsten kommt und alles andere ein schmutziger Hack wäre.