Frage

goto ist fast universell entmutigt. Lohnt es sich jemals, diese Aussage zu verwenden?

War es hilfreich?

Lösung

Dies wurde mehrmals auf Stack Overflow und Chris Gillum besprochen fasste die möglichen Verwendungen von zusammen goto:

Eine Funktion sauber verlassen

In einer Funktion können Sie häufig Ressourcen zuweisen und an mehreren Stellen verlassen müssen. Programmierer können ihren Code vereinfachen, indem sie den Ressourcenreinigungscode am Ende der Funktion alle "Exit -Punkte" der Funktion auf das Reinigungsetikett aufnehmen. Auf diese Weise müssen Sie nicht an jedem "Beendepunkt" der Funktion Reinigungscode schreiben.

Verschachtelte Schleifen verlassen

Wenn Sie sich in einer verschachtelten Schleife befinden und ausbrechen müssen alle Loops, ein Goto kann so viel sauberer und einfacher machen als Break-Anweisungen und If-Checks.

Leistungsverbesserungen auf niedriger Ebene

Dies gilt nur in einem perfizierenden Code, aber GOTO-Anweisungen werden sehr schnell ausgeführt und können Sie beim Durchziehen einer Funktion einen Schub geben. Dies ist jedoch ein zweischneidiges Schwert, da ein Compiler den Code, der Gotos enthält, normalerweise nicht optimieren kann.

Ich würde argumentieren, wie viele andere argumentieren würden, dass in all diesen Fällen die Verwendung von goto wird als Mittel verwendet, um aus einer Ecke herauszukommen, in die man sich kodiert, und ist im Allgemeinen ein Symptom für Code, das neu gestaltet werden könnte.

Andere Tipps

Übergangsströmungskonstrukte auf höherer Ebene entsprechen tendenziell Konzepten in der Problemdomäne. A if/sonst ist eine Entscheidung, die auf einer Bedingung basiert. Eine Schleife sagt, dass sie wiederholt einige Aktionen ausführen soll. Sogar eine Break -Erklärung sagt "Wir haben das wiederholt gemacht, aber jetzt müssen wir aufhören."

Eine GOTO -Erklärung dagegen entspricht tendenziell einem Konzept im laufenden Programm, nicht im Problembereich. Es heißt, die Ausführung an einem bestimmten Punkt fortzusetzen im Programm. Jemand, der den Code liest schließen Was bedeutet dies in Bezug auf die Problemdomäne.

Natürlich können alle Konstrukte auf höherer Ebene in Bezug auf Gotos und einfache bedingte Zweige definiert werden. Das bedeutet nicht, dass sie nur Gotos in Verkleidung sind. Denken Sie an sie als eingeschränkt Gotos - und es sind die Einschränkungen, die sie nützlich machen. Eine Break -Anweisung wird als Sprung bis zum Ende der umschließenden Schleife implementiert, aber es wird besser als auf der gesamten Schleife betrachtet.

Alles andere ist gleich, der Code, dessen Struktur die der Problemdomäne widerspiegelt, ist tendenziell leichter zu lesen und zu warten.

Es gibt keine Fälle, in denen eine GOTO -Erklärung absolut erforderlich ist (da ist es ein Satz zu diesem Zweck), aber es gibt Fälle, in denen es die am wenigsten schlechte Lösung sein kann. Diese Fälle variieren von Sprache zu Sprache, je nachdem, was die Sprache unterstützt.

In C zum Beispiel glaube ich, dass es drei grundlegende Szenarien gibt, in denen ein GOTO angemessen ist.

  1. Aus einer verschachtelten Schleife ausbrechen. Dies wäre unnötig, wenn die Sprache eine bezeichnete Break -Erklärung hätte.
  2. Rettung aus einem Codeabschnitt (typischerweise einer Funktionskörper) bei einem Fehler oder einem anderen unerwarteten Ereignis. Dies wäre unnötig, wenn die Sprache Ausnahmen hätte.
  3. Implementierung einer expliziten endlichen Zustandsmaschine. In diesem Fall (und wie ich denke nur in diesem Fall) entspricht ein Goto direkt einem Konzept in der Problemdomäne, wobei der Übergang von einem Zustand in einen bestimmten anderen Zustand übergeht, in dem der aktuelle Zustand dargestellt wird, durch den derzeit Codeblock ausführt wird .

Andererseits kann auch eine explizite endliche Zustandsmaschine mit einer Switch -Anweisung in einer Schleife implementiert werden. Dies hat den Vorteil, dass jeder Staat an derselben Stelle im Code beginnt, was zum Beispiel zum Debuggen nützlich sein kann.

Die Hauptverwendung eines GOTO in einer einigermaßen modernen Sprache (eine, die stützt, ob/sonst und Loops), besteht darin, ein Steuerflusskonstrukt zu simulieren, das in der Sprache fehlt.

Sicherlich hängt es von der Programmiersprache ab. Der Hauptgrund goto Es war umstritten, dass es sich um seine negativen Auswirkungen handelt, die sich ergeben, wenn der Compiler es zu großzügig nutzen kann. Probleme können beispielsweise auftreten, wenn Sie es verwenden können goto Auf diese Weise können Sie jetzt auf eine nicht initialisierte Variable zugreifen oder schlimmer noch in eine andere Methode springen und sich mit dem Anrufstapel anlegen. Es sollte in der Verantwortung des Compilers liegen, den unsinnigen Kontrollfluss zu verbieten.

Java hat versucht, dieses Problem durch Ablehnung zu „lösen“ goto völlig. Mit Java können Sie jedoch verwenden return in einem finally Blockieren und somit eine Ausnahme bewirken, um versehentlich verschluckt zu werden. Das gleiche Problem ist immer noch da: Der Compiler macht seinen Job nicht. Entfernen goto Aus der Sprache hat es nicht behoben.

In C#, goto ist so sicher wie break, continue, try/catch/finally und return. Sie können nicht uneingeschränkte Variablen verwenden, sondern Sie können nicht aus einem endgültigen Block springen usw. Der Compiler beschwert sich. Dies liegt daran, dass es das löst real Problem, das ist wie ich sagte, unsinnigen Kontrollfluss. goto Stornieren Sie die Analyse der definitiven Analyse und andere angemessene Compiler-Überprüfungen nicht auf magische Weise.

Ja. Wenn Ihre Schleifen mehrere Ebenen tief verschachtelt sind, goto ist der nur Art, elegant aus einer inneren Schleife auszubrechen. Die andere Option besteht darin, ein Flag einzustellen und aus jeder Schleife auszubrechen, wenn dieses Flag eine Bedingung erfüllt. Das ist wirklich hässlich und ziemlich fehleranfällig. In diesen Fällen, goto ist einfach besser.

Natürlich ist Java beschriftet break Die Anweisung tut dasselbe, ohne zu erlauben, zu einem willkürlichen Punkt im Code zu springen, was das Problem ordentlich löst, ohne die Dinge zuzulassen, die machen goto teuflisch.

Das Beste aus der Entmutigung kommt eine Art "Religion", die hergestellt wurde, Gott Djikstra, die in den frühen 60ern über ihre wahllose Kraft zwangsläufig war:

  • Springen Sie überall in den Codeblock
    • Funktion, die nicht von Anfang an ausgeführt wird
    • Schleifen, die von Anfang an nicht ausgeführt werden
    • Variable Initialisierung übersprungen
  • Springen Sie von dem Codeblock ohne mögliche Reinigung weg.

Dies hat nichts mehr mit dem zu tun goto Aussage der modernen Sprachen, deren Existenz lediglich die Erstellung von anderen Codestrukturen als die mit der vorgesehenen Sprache unterstützt.

Insbesondere der erste Hauptpunkt oben ist noch erlaubt und der zweite wird gereinigt (wenn Sie goto Aus einem Block ist der Stapel richtig unerschlossen und alle richtigen Zerstörer genannt)

Sie können sich beziehen Diese Antwort Eine Vorstellung davon zu haben, wie sogar Code, das Goto nicht verwendet, unlesbar sein kann. Das Problem ist nicht selbst, sondern die schlechte Verwendung.

Ich kann ein ganzes Programm schreiben, ohne zu verwenden if, nur for. Natürlich wird es nicht gut lesbar sein, ein ungeschickter und unnötig komplizierter.

Aber das Problem ist nicht for. Da ich bin.

Dinge wie break, continue, throw, bool needed=true; while(needed) {...}, usw. merken mehr als Maskerade goto Um sich von den Scimitaren der Djikstrarier -Eiferer zu entfernen, wollen sie -50 Jahre nach der Erfindung der modernen Verlangen - immer noch ihre Gefangenen. Sie vergaßen, wovon Djikstra sprach, sie erinnern sich nur an den Titel seiner Notiz (goto gilt als schädlich, und es war nicht einmal sein ONW -Titel: Er wurde vom Herausgeber geändert) und beschuldigte und bash, bash und beschuldigte jeden Publikum, den diese 4 haben. Brief in Sequenz platziert.

Es ist 2011: Es ist Zeit, das zu verstehen goto hat bemerkt, mit dem umzugehen GOTO Aussage Djikstra war überzeugend.

Die seltsame Goto hier oder da, solange es für eine Funktion lokal ist, schadet die Lesbarkeit selten erheblich. Es kommt oft zugute, indem es auf die Tatsache aufmerksam macht, dass in diesem Code etwas Ungewöhnliches vorhanden ist, das die Verwendung einer etwas ungewöhnlichen Kontrollstruktur erfordert.

Wenn (lokale) Gotos die Lesbarkeit erheblich schadet, ist dies normalerweise ein Zeichen dafür, dass die Funktion, die das GOTO enthält, zu komplex geworden ist.

Das letzte Goto, den ich in ein Stück C -Code steckte, bestand darin, zwei ineinandergreifende Schleifen zu erstellen. Es passt nicht in die normale Definition der "akzeptablen" Goto -Verwendung, aber die Funktion wurde dadurch deutlich kleiner und klarer. Um die GOTO zu vermeiden, hätte eine besonders unordentliche Verstoß gegen Trocknen erforderlich.

Ich denke, dieses ganze Problem war es, den falschen Baum zu bellen.

Goto als solches scheint mir nicht problematisch zu sein, sondern es ist sehr oft ein Symptom einer tatsächlichen Sünde: Spaghetti -Code.

Wenn der GOTO eine große Überquerung der Flusskontrolllinien verursacht, ist es schlecht, Periode. Wenn es keine Flusssteuerungslinien überschreitet, ist es harmlos. In der grauen Zone dazwischen haben wir Dinge wie Schleifenrettverkäufe, es gibt immer noch einige Sprachen, die keine Konstrukte hinzugefügt haben, die alle legitimalen grauen Fälle abdecken.

Der einzige Fall, den ich 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 Duplizierter Code, eine Flagge oder ein Goto. Ich finde die Goto -Lösung das Beste der drei. Hier gibt es keine Überquerung der Flusssteuerungslinien, es ist harmlos.

Ja, das Goto kann verwendet werden, um der Erfahrung des Entwicklers zugute kommen:http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

Genau wie bei jedem leistungsstarken Werkzeug (Zeiger, multiple Vererbung usw.) muss man diszipliniert werden. Das in der Link angegebene Beispiel verwendet PHP, das die Verwendung des GOTO -Konstrukts auf dieselbe Funktion/Methode beschränkt und die Fähigkeit deaktiviert, in einen neuen Steuerblock zu springen (z. B. Schleife, Switch -Anweisung usw.).

Hängt von der Sprache ab. Es wird beispielsweise immer noch in der COBOL -Programmierung verwendet. Ich habe auch an einem Barionet 50 -Gerät gearbeitet, dessen Firmware -Programmiersprache ein früher grundlegender Dialekt ist, für den Sie GOTO natürlich verwenden müssen.

Ich würde nein sagen. Wenn Sie die Notwendigkeit von GOTO verwenden, wette ich, dass der Code neu gestaltet werden muss.

goto kann nützlich sein, wenn der Legacy-Assembler-Code auf C. in erster Instanz eine Umstellung von Anweisungen zu C in C unter verwendet wird goto Als Ersatz für den Montageer des Assemblers branch Anweisung, kann sehr schnelles Porting ermöglichen.

Ich würde nein argumentieren. Sie sollten immer durch ein Tool ersetzt werden, das spezifischer für das Problem ist, mit dem die GOTO gelöst wird (es sei denn, es ist in Ihrer Sprache nicht verfügbar). Beispielsweise lösen Break-Anweisungen und Ausnahmen auf zuvor gelöste Probleme der Schleife und Fehlerbehandlung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top