GoSuda

Warum gibt es in Go kein Try-Catch?

By Rabbit Princess
views ...

Go unterstützt absichtlich kein try-catch, sondern lediglich die panic-recover-Syntax. Dies stößt bei zahlreichen Entwicklern, die an die Fehlerbehandlung mittels try-catch gewöhnt sind, auf Unmut. Warum aber wird try-catch nicht implementiert? Der Grund liegt darin, dass try-catch verschiedene Probleme aufweist.

try-catch-finally

Die try-catch-Anweisung ist eine Syntax zur Behandlung von Fehler- und Ausnahmesituationen, die während der Programmausführung (Laufzeit) auftreten können. Die finally-Anweisung enthält Code, der unabhängig davon, ob eine Ausnahme auftritt oder nicht, in jedem Fall ausgeführt werden muss.

Fehlerbehandlung und Verantwortung

In den 80er und 90er Jahren war die Fehlerbehandlung sehr einfach. Fehlermeldungen beschränkten sich auf 'Diskette voll', 'Keine Diskette im Laufwerk' oder 'Keine Schreibberechtigung für Diskette'. Entwickler dieser Ära warfen Fehler bis zu einem gemeinsamen Fehlerbehandlungspunkt, um sie dort zu verarbeiten. In diesem Kontext funktionierte die try-catch-Anweisung effizient.

Mit der Zeit änderte sich die Situation jedoch. Die Geschäftslogik wurde komplexer, Datenbanken und Transaktionen entstanden, und es mussten unzählige API-Aufrufe über das Netzwerk getätigt und unzählige Request-Nachrichten interpretiert werden. Zudem führte das Aufkommen der Parallelprogrammierung dazu, dass Fehler in anderen Threads als dem Hauptthread behandelt werden mussten.

Fehler wurden so komplex, dass sie nicht mehr an einer einzigen Stelle behandelt werden konnten, und niemand konnte mehr die volle Verantwortung für alle Fehler übernehmen. Hierin liegt ein gravierendes Problem von try-catch.

Verantwortungsdelegation durch try-catch

try-catch ist, kurz gesagt, eine Methode, bei der die Entität, die einen Fehler verursacht, die Verantwortung (die Nachbereitung) an jemand anderen delegiert. Dieses Ziel kann die catch-Anweisung, die übergeordnete Methode oder sogar der übergeordnete Vorfahre des übergeordneten Vorfahren sein. Anders ausgedrückt, in einer Welt, in der die Fehlerbehandlung zunimmt und komplexer wird, ist der Ansatz von try-catch schlichtweg: "Irgendjemand wird es schon machen." Betrachten wir den folgenden Code:

1try {
2    data = readFile("hello.txt");
3    structuredData = parseData(data);
4    insertDBStatus(structuredData[1]);
5    startHTTPServer(structuredData[2]);
6} catch (Exception e) {
7    e.printStackTrace();
8}

Das Problem mit dem obigen Code ist, dass weder klar ist, wer für die Verarbeitung von printStackTrace zuständig ist, noch wo der Fehler im Code aufgetreten ist. Je mehr Logik in der try-Anweisung enthalten ist, desto schlimmer wird das Problem. Paradoxerweise wurden Entwickler jedoch, je komplexer die Entwicklung wurde, umso stärker von den try-catch-Anweisungen zur Verantwortungsdelegation abhängig. Sie machten sich keine Gedanken mehr über die Fehlerbehandlung, ihr Verantwortungsbewusstsein nahm ab, und letztendlich vergaßen sie die Essenz der Fehler- und Ausnahmebehandlung. Wie löst Golang dieses Problem?

panic, recover

Einer der Vorteile von Go ist, dass es verschiedene Systeme gibt, die Entwickler dazu anhalten, gute Praktiken zu befolgen, anstatt sie in schlechte Gewohnheiten abzdriften zu lassen. panic - recover ist ein solches Beispiel.

Auf den ersten Blick scheinen panic und recover keinen Unterschied zu try-catch aufzuweisen, doch sie unterscheiden sich darin, dass sie die Verantwortung bei einem Problem nicht nach außen verlagern. Wenn in Go ein panic auftritt, sollte der Wert nicht nach außen geleitet, sondern an der Stelle behoben werden, an der der panic aufgetreten ist. Dies überträgt die Verantwortung für die Fehlerbehandlung auf den Entwickler und regt ihn dazu an, eingehender darüber nachzudenken, wo, wer und wie der Fehler behandelt werden sollte. Dies gewährleistet dem Benutzer Autonomie und lässt gleichzeitig Raum zum Nachdenken.

Darüber hinaus ist die Wahl des Wortes "panic" äußerst treffend. Im Gegensatz zu try-recover übt panic-recover allein durch das Wort einen Druck auf den Entwickler aus, es nur in klaren Fehlersituationen und nicht in Ausnahmesituationen zu verwenden. Natürlicherweise missbraucht der Entwickler recover nicht, sondern setzt es nur dort ein, wo es wirklich notwendig ist. Dies trägt maßgeblich dazu bei, in Go prägnanten Code zu schreiben.