Super kurze Zusammenfassung: Es kann eine gute Idee sein, Ihr Programm zu beenden, wenn Sie eine Fehlermeldung erhalten. Die Verwendung von Gobail wird Ihr Leben einfacher machen.
Wenn in Ihrem Go-Code ein Fehler auftritt, sehen Sie normalerweise etwa Folgendes:
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
In diesem Beispiel werden Ihnen einige Dinge auffallen:
Was passiert also als nächstes? Nun, es passiert alles wieder. Sie überprüfen den Fehlerwert, beschreiben ihn und geben ihn zurück. Und dann geht alles von vorne los.
Warum machen wir das? Warum dieser ganze Aufwand?
Nun, es hängt alles von der Software ab, die Sie schreiben. Wenn Sie einen Fehler erhalten, müssen Sie eine Entscheidung treffen. Was passiert mit diesem Fehler?
Wenn Sie eine HTTP-API schreiben, die auf eine Anfrage antwortet, gelangen Sie irgendwann zu einer Art HTTP-Handler und wandeln diesen Fehler in eine Antwort um – vielleicht eine kleine 400 mit einem höflichen Erinnerungsformat Anfragen ordnungsgemäß oder möglicherweise eine 500 und eine besorgniserregende Meldung über den Zustand Ihrer Anwendung. Wenn Sie alternativ ein CLI-Tool schreiben, könnten Sie entscheiden, dass der Fehler letztendlich an Ihre Hauptfunktion zurückgereicht wird. Bei jeder Art von Programm könnten Sie entscheiden, dass genug genug ist – das Programm sollte einfach enden, weil Sie nichts anderes tun können.
Sehen wir uns diese letzte Option an. Wann ist es angebracht, Ihr Programm einfach zu beenden? Hier sind ein paar Gründe, die mir einfallen:
a. Es bleibt nichts anderes zu tun, der Fehler ist so schlimm, dass sofort alles aufhören muss
B. Das Beenden des Programms hat keine Konsequenzen (keine Bereinigung erforderlich, kein Status zum Antworten)
C. Ein frühzeitiges Stoppen ist wünschenswert, vielleicht haben Sie einen Monitor, der den Prozess sauber neu startet
Was auch immer der Grund sein mag, Sie müssen überlegen, wie Sie sauber aussteigen. Das erste, was Sie wahrscheinlich versuchen werden, ist Folgendes:
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
Es sieht unserem ursprünglichen Fehlerbehandlungscode ziemlich ähnlich, weist jedoch einige wichtige Unterschiede auf. Das erste ist irgendwie offensichtlich – da gibt es eine tolle stop-right-g*****n-now-Anweisung. Ihr Programm wird nicht fortgesetzt. Der zweite Punkt ist vielleicht wichtiger. Der Code, der dieses Beispiel aufruft, kümmert sich nicht um die Behandlung von Fehlern. Es gibt keine zusätzlichen Codepfade, die getestet werden müssen – wir können darauf vertrauen, dass der aufrufende Code keinen if-Block zum Testen hat, da nichts zurückgegeben wird, was wir überprüfen müssen.
Also war ich vielleicht ein wenig begeistert, als ich vorschlug, dass Sie einfach darauf vertrauen sollten, dass Ihr Exit-Code einfach funktioniert. Sie sollten wahrscheinlich überprüfen, ob der Grund dafür, dass Ihr neues Programm gestoppt wurde, der richtige Grund ist.
Das scheint einfach zu sein. Hier sind einige Dinge, die Sie beachten sollten: Im einfachsten Fall führen Sie einfach Ihr Programm aus und lösen einen Fehler aus. Lassen Sie beispielsweise Ihr CLI-Tool eine Datei öffnen, die nicht vorhanden ist. In einigen einfachen Fällen können Sie dies manuell tun. Wenn die Anzahl der Tests zunimmt, benötigen Sie wahrscheinlich eine Art Automatisierung, die Ihnen dabei hilft.
Kurze Randbemerkung: Dies ist wahrscheinlich das Thema eines ganz anderen Blog-Beitrags, aber meine derzeitige Lieblingsmethode zum Testen von CLI-Tools verwendet Godog zum Schreiben von Tests. Es kann ein wenig komplex sein, aber ich habe es als überaus kraftvoll empfunden. Hier sind einige gute Beispiele dafür, wie ich es mit Layli und Wait-For angegangen bin.
Dieser Ansatz wird Sie sehr weit bringen, aber manchmal kann es schwierig sein, die Bedingungen zu schaffen, die alle Codepfade, auf die Sie sich verlassen möchten, ordnungsgemäß ausführen.
OK, jetzt werden wir einige der Funktionen der Go-Sprache verwenden. Wir müssen os.Exit nicht unbedingt aufrufen – wir können etwas aufrufen, das so aussieht. Schauen Sie sich also Folgendes an:
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
Wie können wir dies für unsere Tests nutzen? Da die Funktion nun in eine Variable umgewandelt wurde (customExit), können wir den Wert durch etwas anderes ersetzen, das wir tun möchten. So...
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
Dies ist ein viel Unit-Test-freundlicherer Ansatz. Sie können überprüfen, ob der verwendete Exit-Code korrekt ist – und ob Sie die Exit-Funktion tatsächlich aufgerufen haben.
Oberflächlich betrachtet sieht das gut aus, aber es gibt ein großes Problem: Wenn Ihr Test erfolgreich ist, fährt Ihr Programm fort und führt den Rest der Funktion aus, wenn Sie erwartet haben, dass sie beendet wird. Es wird fortgesetzt, auch wenn der Testaufbau bedeutet, dass der Rest der Ausführung ungültig ist und Probleme für Ihre Tests verursacht, z. B. Panik.
Nun, das klingt ein bisschen extrem!
Ich habe das Gefühl, dass ich es erklären sollte ... Normalerweise müssen Sie in „gut geführten“ Unternehmen sicherstellen, dass jede Codezeile nachweislich funktioniert, bevor sie Ihren Kunden präsentiert werden kann. Mit den oben genannten Techniken können Sie möglicherweise nicht die richtigen Abdeckungsmetriken generieren, um zu bestätigen, dass Sie gut sind. Auch wenn es trivial ist, darüber nachzudenken.
Bei allen obigen Beispielen wurde davon ausgegangen, dass wir, wenn wir einen Fehler erhalten, diesen überprüfen müssen, um zu entscheiden, was zu tun ist (Abbruch mit Rache). Wäre es nicht großartig, wenn wir den Vorgang beenden könnten, ohne überprüfen zu müssen, ob ein Fehler vorliegt?
Mal sehen, was wir tun können.
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
Sehen Sie sich das obige Beispiel an. Die Funktionalität ist dieselbe, aber die Implementierung von myFunc ist jetzt viel einfacher – es gibt keine Bedingungen. Wir können die Implementierung der checkExit-Funktion in ihren eigenen Tests überprüfen, was bedeutet, dass alles, was in myFunc() neu ist, viel einfacher überprüft werden kann.
Es wurde eine neue Bibliothek, Gobail, erstellt, mit der Sie sicher sein können, dass ein Fehler behoben wird, ohne dass Sie Ihrem eigenen Code Komplexität hinzufügen müssen. Es sieht so aus:
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
Diese Bibliothek wurde vollständig mit Abdeckungsmetriken getestet, um dies zu beweisen. Sie können es sicher verwenden, ohne befürchten zu müssen, dass ein Fehler übersprungen wird. Es werden auch Funktionen mit zwei Rückgabewerten verarbeitet, etwa so:
type ExitFunc func(code int) var customExit ExitFunc = os.Exit func myFunc() { err := someOtherFunc() if err != nil { fmt.Printf("doing my thing: %v", err) customExit(1) } }
Beachten Sie auch, dass Sie den Fehler angeben, der alle Ihre Probleme verursacht.
Es ist auch möglich, in Panik zu versetzen, statt es zu beenden, und einen Stack-Trace und andere Kontextinformationen aus dem Programm auszudrucken, wenn die Panik ausgelöst wird. Weitere Informationen finden Sie in den Dokumenten.
Wenn Sie Software mit gobail schreiben, werden Sie feststellen, dass Sie diese meist verwenden müssen, wenn Sie mit externen Bibliotheken kommunizieren. Dieser enthält den zusätzlichen Code, den Sie normalerweise schreiben müssen, um alle Fehlerfälle zu behandeln. Er kann in einen Aufruf von Return oder Return2 eingeschlossen werden und davon ausgehen, dass wir bei Bedarf beenden.
Manchmal ist es wünschenswert, Ihr Programm zu beenden, anstatt Ihre Fehler im Detail zu behandeln. Die Gobail-Bibliothek wurde erstellt und validiert, sodass Sie sich nicht um die Einzelheiten des Nachweises kümmern müssen.
Wenn Sie eine Verbesserung finden, die gemacht werden könnte, oder einfach nur einen Vorschlag haben, dann melden Sie eine PR oder ein Problem im Repo und die Entwickler werden sich darum kümmern, wenn sie können!
Das obige ist der detaillierte Inhalt vonFrüh aufgeben für den Sieg!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!