Wann sollten os.Exit () und Panic () verwendet werden?

92

Könnte jemand die wichtigsten Unterschiede zwischen os.Exit()und erklären, panic()wie sie in Go in der Praxis verwendet werden?

Timur Fayzrakhmanov
quelle
11
Nur ein Kommentar, der hoffentlich beim zukünftigen Lesen von Go-Code helfen wird: In vielen Beispielcodes panicwird er zum Beenden von Fehlern verwendet, nur weil er leicht zu verstehen ist und das Importieren anderer Pakete entfällt. Dies bedeutet nicht, dass es eine gute oder idiomatische Praxis ist! . Es ist nur ein platzsparendes Gerät, zum Beispiel Code. IRL-Reserve panicfür ganz besondere Situationen.
Internet
1
Hm..gut) besonders "IRL" Abkürzung - es ist neu für mich :) Können Sie erklären, wie Panik den Paketimport eliminiert?
Timur Fayzrakhmanov
4
panicist ein eingebauter. Es wird empfohlen , (je nach Umständen) etwas ähnliches zu verwenden os.Exit, log.Fataletc., die einen Fehlercode an das Betriebssystem zurückkehren werden (immer wenn möglich empfohlen). Dies alles beinhaltet das Importieren eines Pakets und damit das "Durcheinander" des Beispielcodes. Beispielcode sollte immer nur verwendet werden, um eine Lösung für ein bestimmtes Problem zu demonstrieren. Es kann andere Probleme mit dem Code geben, die den Code komplexer machen, wenn sie richtig demonstriert werden, und daher die Erklärung der gegebenen Antwort beeinträchtigen. YMMV.
Internet
1
Ok, verstanden!)
Vielen
2
NP, gerne helfen und Ihr akronymisches Lexikon erweitern :-)
Intermernet

Antworten:

83

Wenn Sie eine Frage zur Verwendung in der Praxis haben, sollten Sie zunächst den Go-Quellcode (oder eine ausreichend große Go-Codebasis) und die Paketdokumente nach Antworten durchsuchen .

Nun os.Exitund panicsind ganz anders. panicwird verwendet, wenn das Programm oder sein Teil einen nicht wiederherstellbaren Zustand erreicht hat.

Wenn panices aufgerufen wird, auch implizit für Laufzeitfehler wie das Indizieren eines Slice außerhalb der Grenzen oder das Fehlschlagen einer Typzusicherung, stoppt es sofort die Ausführung der aktuellen Funktion und beginnt, den Stapel der Goroutine abzuwickeln, wobei alle zurückgestellten Funktionen ausgeführt werden. Wenn dieses Abwickeln die Spitze des Stapels der Goroutine erreicht, stirbt das Programm.

os.Exitwird verwendet, wenn Sie das Programm sofort abbrechen müssen. ohne die Möglichkeit einer Wiederherstellung oder Ausführung einer verzögerten Bereinigungsanweisung, und außerdem einen Fehlercode zurückgeben müssen (den andere Programme verwenden können, um zu melden, was passiert ist). Dies ist in Tests hilfreich, wenn Sie bereits wissen, dass nach dem Fehlschlagen dieses einen Tests auch der andere fehlschlägt. Sie können ihn also genauso gut jetzt beenden. Dies kann auch verwendet werden, wenn Ihr Programm alles getan hat, was es tun muss, und jetzt nur noch beendet werden muss, dh nachdem eine Hilfemeldung gedruckt wurde.

Die meiste Zeit werden Sie nicht verwenden panic(Sie sollten errorstattdessen eine zurückgeben), und Sie benötigen fast nie os.Exitaußerhalb einiger Fälle in Tests und für eine schnelle Programmbeendigung.

Ainar-G
quelle
9
"Dies ist in Tests nützlich, wenn Sie bereits wissen, dass nach dem Fehlschlagen dieses einen Tests auch der andere fehlschlägt ..." Dies riecht nach einem Test-Anti-Muster abhängiger Tests. In einer gut geschriebenen Testsuite ist jeder Test unabhängig. Das Ergebnis eines bestimmten Tests sollte niemals das Ergebnis eines anderen Tests bestimmen.
Gotgenes
1
@gotgenes Nicht unbedingt. Wenn ich einen Test habe, bei dem eine bestimmte Funktion eine Nicht-Null-Struktur zurückgibt und dieser Test fehlschlägt, kann ich davon ausgehen, dass alle Tests, die die Werte der Struktur untersuchen, ebenfalls fehlschlagen. Es ist der Code, der abhängig ist, nicht die Tests. (Das heißt, ich würde exitin diesem Fall nicht verwenden , ich würde nur einen großen Stapel fehlgeschlagener Behauptungen erwarten.)
David Moles
83

Erstens os.Exit()kann verwendet werden, um das Programm normal ohne Fehler zu beenden, und nicht in Panik, so dass dies eine wichtige Unterscheidung ist. Ein weiterer Grund ist, dass Panik irgendwo abgefangen und ignoriert oder mit protokolliert werden kann recover.

Wenn es sich jedoch um einen fehlerhaften Exit-Code handelt, sagen wir:

Verwenden Sie diese panicOption, wenn etwas furchtbar schief geht, wahrscheinlich ein Programmiererfehler, der vor dem Start der Produktion hätte abgefangen werden müssen. Aus diesem Grund wird der Stapel gedruckt.

Verwenden Sie os.Exit(errorCode)oder so etwas, wenn Sie möchten:

  1. Steuern Sie den Exit-Code des Programms für Skriptzwecke.

  2. Sie möchten einen ordnungsgemäßen Beenden eines erwarteten Fehlers (z. B. Benutzereingabefehler).

Panik ist also im Grunde genommen für Sie, ein schlechter Exit-Code ist für Ihren Benutzer.

Not_a_Golfer
quelle
Vielen Dank sehr hilfreich!)
Timur Fayzrakhmanov
14
"Panik ist also im Grunde genommen für Sie, ein schlechter Exit-Code ist für Ihren Benutzer." <-
Super
1
Können wir sagen, dass Panic () irgendwie mit dem üblichen assert () -Aufruf in C zusammenhängt? Nun, ich weiß, ich entferne immer einen bestätigenden Anruf, bevor ich zur Produktion gehe. Ich aktiviere sie nur, wenn ich eine neue Funktion teste. Was ich damit sagen will ist, dass ich meistens assert () verwende, um Invarianten zu überprüfen, von denen ich denke, dass sie in meinem Code wahr sein müssen. Sehen Sie die gleiche Verwendung für Panic ()? :-)
yves Baumes
7

Die Hauptunterschiede sind:

  1. os.Exit überspringt die Ausführung der verzögerten Funktion.
  2. Mit os.Exitkönnen Sie den Exit-Code angeben.
  3. panicwird beendet, solange dies os.Exitnicht der Fall ist. (Andere Antworten scheinen dies nicht zu erwähnen.)

Wenn Sie die verzögerte Funktion ausführen müssen, haben Sie keine andere Wahl panic. (Wenn Sie andererseits die Ausführung der verzögerten Funktion überspringen möchten, verwenden Sie os.Exit.)

Wenn eine nicht leere Funktion folgendermaßen definiert ist:

  1. Die Funktion enthält viele Zweige
  2. Alle Zweige werden mit returnoder beendetpanic

Dann können Sie nicht ersetzen panicmit os.Exitsonst der Compiler ablehnen wird das Programm zu kompilieren, „fehlende Rückkehr am Ende der Funktion“ zu sagen. (Go ist hier sogar sehr dummlog.Panic keine Funktion.)

Unter anderen Bedingungen:

  1. Verwenden panic wenn etwas wirklich Verdrahtetes passiert, z. B. ein Programmierlogikfehler.
  2. Verwenden os.ExitSie diese Option, wenn Sie einen sofortigen Exit mit dem angegebenen Exit-Code wünschen.
schwach
quelle