Proč Go nemá Try-Catch?
Go záměrně nepodporuje try-catch a podporuje pouze syntaxi panic-recover. To vyvolává odpor mnoha vývojářů, kteří jsou zvyklí na zpracování chyb pomocí try-catch. Proč tedy nebyl try-catch implementován? Je to proto, že try-catch má několik problémů.
try-catch-finally
Příkaz try-catch slouží ke zpracování chybových a výjimečných situací, které mohou nastat během provádění programu (runtime). Příkaz finally navíc určuje kód, který se musí provést bez ohledu na to, zda došlo k výjimce.
Zpracování chyb a odpovědnost
V 80. a 90. letech bylo zpracování chyb velmi jednoduché. Chybové zprávy byly pouze 'Disketa plná', 'Disketa není v jednotce', 'Disketa nemá oprávnění pro zápis', a vývojáři v té době, když se vyskytla chyba, ji hodili (throw) až do bodu zpracování chyb, kde byla zpracována společně. V této situaci fungoval příkaz try-catch efektivně.
Časem se však situace změnila. Obchodní logika se zkomplikovala, objevily se databáze a transakce, a s voláním mnoha API prostřednictvím sítě bylo nutné analyzovat množství request zpráv. Dokonce i s příchodem souběžného programování bylo nutné zpracovávat chyby v jiných vláknech než v hlavním.
Chyby se staly natolik složitými, že je nelze zpracovávat na jednom místě, a nikdo nemůže nést odpovědnost za všechny chyby. Zde vzniká vážný problém s try-catch.
Přenesení odpovědnosti try-catch
Try-catch je jednoduše způsob, jakým subjekt, který chybu způsobil, přenese odpovědnost (uklízení) za výskyt chyby na někoho jiného. Tímto 'někým jiným' může být klauzule catch, jeho nadřazená metoda, nebo nadřazená metoda jeho nadřazené metody a tak dále. Jinými slovy, ve světě, kde je zpracování chyb stále rozsáhlejší a složitější, je metoda try-catch 'někdo to udělá za mě'. Podívejme se na následující kód.
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}
Problémem výše uvedeného kódu je, že není jasné, kdo je zodpovědný za zpracování printStackTrace, a není ani možné zjistit, ve kterém kódu došlo k chybě. A dokonce i když se v příkazu try objeví více logiky, problém se ještě zhoršuje. Paradoxně však platí, že čím složitější je vývoj, tím více jsou vývojáři závislí na try-catch, která přenáší odpovědnost, a nepřemýšlejí o zpracování chyb, snižuje se jejich smysl pro odpovědnost, a nakonec zapomínají na podstatu zpracování chyb a výjimek. Jak tedy tento problém vyřešil Golang?
panic, recover
Jednou z výhod Go je, že má několik systémů, které vývojáře nevedou špatnou cestou a dělají z nich dobré vývojáře. Panic - recover je také jeden z příkladů.
Panic a recover se na první pohled zdají být stejné jako try-catch, ale liší se v tom, že při vzniku problému nepřesouvají odpovědnost ven. Když v Go dojde k panice, hodnota se nevrací ven, ale řešení by se mělo provést v místě, kde panika nastala. To ukládá vývojáři odpovědnost za zpracování chyb a nutí ho, aby hlouběji přemýšlel o tom, kde, kdo a jak by se měla chyba zpracovat. Je to způsob, jak zaručit uživateli autonomii a zároveň mu ponechat prostor k přemýšlení.
Výběr slova panic je také velmi vynikající. Na rozdíl od try-recover, panic-recover již samotnými slovy nutí vývojáře používat ho pouze v jasných chybových situacích, a ne v situacích výjimečných. Vývojář přirozeně zneužívá recover méně a používá ho pouze tam, kde je to nutné. To je velká pomoc při psaní stručného kódu v Go.