GoSuda

Miért nincs try-catch blokk a Go programozási nyelvben?

By Rabbit Princess
views ...

A go nyelvi környezet szándékosan nem támogatja a try-catch mechanizmust, csak a panic-recover nyelvtani szerkezetet. Ez számos, a try-catch hibakezelési módszerhez szokott fejlesztő elégedetlenségét váltotta ki. Miért nem implementálták a try-catch-et? Mert a try-catch számos problémát rejt magában.

try-catch-finally

A try-catch (try-catch) utasítás a program futása közben (runtime) fellépő hiba- és kivételes helyzetek kezelésére szolgál. A finally utasítás pedig olyan kódrészleteket tartalmaz, amelyeknek feltétlenül végre kell hajtódniuk, függetlenül attól, hogy kivétel történt-e vagy sem.

Hiba kezelés és felelősség

A 80-as és 90-es években a hiba kezelése nagyon egyszerű volt. A hibaüzenetek a következőkből álltak: „Floppy lemez tele”, „Nincs floppy lemez a meghajtóban”, „Nincs írási jogosultság a floppy lemezre”, és a fejlesztők a hiba felmerülésekor a hibát a hiba kezelési pontra dobva (throw) közösen kezelték azokat. Ebben a környezetben a try-catch utasítás hatékonyan működött.

Azonban az idő múlásával a helyzet megváltozott. Az üzleti logika bonyolultabbá vált, megjelentek az adatbázisok és a tranzakciók, számos API-t hívtak meg hálózaton keresztül, ami rengeteg kérési üzenet értelmezését igényelte, sőt, a párhuzamos programozás megjelenésével a főszálon kívüli, más szálakban is kellett hibákat kezelni.

A hibák kezelése túl bonyolulttá vált ahhoz, hogy egy helyen lehessen elvégezni, és már nem lehetett egyetlen helyen felelősséget vállalni minden hibáért. Itt jelentkezik a try-catch komoly problémája.

A try-catch felelősségáthárítása

A try-catch lényegében azt jelenti, hogy a hiba kiváltója a hiba kezelésének (utókezelés) felelősségét valakire áthárítja. Ez a „valaki” lehet a catch utasítás, a szülő metódus, vagy akár a szülő szülőjének a szülőjének… a szülője. Más szavakkal, egyre bonyolultabb hiba kezelési világban a try-catch által választott módszer az „már majd valaki megoldja” elv. Nézzük meg az alábbi kódot.

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}

A fenti kód problémája, hogy nem egyértelmű, hogy ki kezeli a printStackTrace-t, és hogy melyik kódrészletben történt a hiba. Sőt, minél több logika kerül a try utasításba, annál rosszabb a helyzet. Paradox módon azonban, minél bonyolultabbá válik a fejlesztés, annál inkább a fejlesztők a felelősségáthárító try-catch utasítás rabjai lesznek, nem foglalkoznak a hiba kezeléssel, felelősségtudatuk gyengül, és végül elfelejtik a hiba- és kivételkezelés lényegét. Hogyan oldotta meg ezt a golang?

panic, recover

A go egyik előnye, hogy számos olyan rendszerrel rendelkezik, amelyek nem engedik, hogy a fejlesztők rossz útra térjenek, hanem jó fejlesztővé váljanak. A panic-recover is ilyen példa.

A panic és a recover első pillantásra nem különbözik a try-catch-től, de abban különbözik, hogy a probléma felmerülésekor nem hárítja át a felelősséget külsőleg. Ha go-ban panic történik, a programnak a panic helyén kell megoldást találnia, nem pedig a hibát kifelé átadni. Ez a fejlesztőre hárítja a hiba kezelésének felelősségét, arra kényszerítve, hogy alaposabban fontolja meg, hol, ki és hogyan kell kezelni a hibát. A felhasználónak szabadságot biztosít, de teret hagy a gondolkodásra.

A panic szó megválasztása is nagyon jó, mert a try-recover-rel ellentétben a panic-recover egyértelműen csak nyilvánvaló hibahelyzetekben használható, ami nyomást gyakorol a fejlesztőre. A fejlesztő így nem fogja túlzásba vinni a recover használatát, csak a szükséges helyeken alkalmazza. Ez nagyban segíti a go-ban a tömör kód írását.