In Rust zijn er geen gebruikelijke uitzonderingen (exceptions) zoals in Java of C++; in plaats daarvan worden de wrapper-typen Result en Option gebruikt om fouten terug te geven.
Result<T, E> - bevat of een waarde (Ok(T)), of een fout (Err(E)). Dit wordt meestal toegepast voor operaties die mogelijk niet correct kunnen worden uitgevoerd (bijvoorbeeld bestandsinvoer/-uitvoer).
Option<T> - voor optionele waarden: ofwel Some(T), ofwel None, zonder foutinformatie. Voorbeeld:
fn divide(x: f64, y: f64) -> Option<f64> { if y == 0.0 { None } else { Some(x / y) } }
In Rust zijn er geen uitzonderingen in de stijl van try/catch om een transparante, beheersbare stroom van fouten te waarborgen en geen garbage collector of unwind-engine te vereisen voor de ondersteuning van uitzonderingen.
Waarom kan panic! niet worden gebruikt voor normale foutafhandeling?
Antwoord: panic! beëindigt de uitvoeringstroom, geeft niet de mogelijkheid om te herstellen en leidt tot unwinding/abort. Wanneer fouten worden teruggegeven via Result, kan de aanroepende partij ze behandelen. Voorbeeld:
fn foo() -> Result<(), String> { Err("Er is iets misgegaan".to_string()) } // in plaats van fn foo() { panic!("Er is iets misgegaan"); }
Verhaal
In een microservice voor beeldverwerking gebruikte de ontwikkelaar
panic!voor de afhandeling van alle onvoorziene situaties. Dit leidde tot een onverwachte beëindiging van de service bij elke fout in plaats van een correcte HTTP-respons naar de client met foutdetails te retourneren.
Verhaal
In een CLI-tool werd
unwrap()voor alle invoer/uitvoer gebruikt, zonder mogelijke fouten te verwerken. Als gevolg hiervan eindigde het programma gewoon zonder enige boodschap of diagnose bij een bestandsfout.
Verhaal
In een analytics-service probeerden ze Option te gebruiken voor elke kleinste fout, waardoor ze informatie over de eigenlijke fouten verloren, wat debuggen moeilijk maakte. Na de overstap naar Result met enumeratiefouten werd het gemakkelijker om bugs te vinden en op te lossen.