programowanieProgramista systemowy

Opisz, jak w Rust obsługiwane są błędy. Jaka jest różnica między panic!, Result i Option? Dlaczego w Rust nie używa się wyjątków (exceptions)?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W Rust nie ma tradycyjnych wyjątków (exceptions) jak w Javie czy C++; zamiast tego używane są typy opakowujące Result i Option do zwracania błędów.

  • Result<T, E> — przechowuje albo wartość (Ok(T)), albo błąd (Err(E)). Zwykle stosuje się go do operacji, które mogą nie zostać poprawnie wykonane (na przykład wejście/wyjście plikowe).

  • Option<T> — dla wartości opcjonalnych: albo Some(T), albo None, bez informacji o błędzie. Przykład:

fn divide(x: f64, y: f64) -> Option<f64> { if y == 0.0 { None } else { Some(x / y) } }
  • panic! — powoduje awaryjne zakończenie działania, w formacie „błąd krytyczny” lub „assert”. Należy go używać tylko w przypadku naruszeń inwariantów, a nie do obsługi błędów użytkownika.

W Rust nie ma wyjątków w stylu try/catch, aby zapewnić przejrzysty, kontrolowany przepływ błędów i nie wymagać zbieracza śmieci ani mechanizmu unwind do utrzymania wyjątków.

Pytanie z podstępem

Dlaczego panic! nie można używać do zwykłej obsługi błędów?

Odpowiedź: panic! kończy strumień wykonania, nie daje możliwości odzyskania, prowadzi do unwinding/abort. Jeśli błędy są zwracane przez Result, strona wywołująca może je obsłużyć. Przykład:

fn foo() -> Result<(), String> { Err("Coś poszło nie tak".to_string()) } // zamiast fn foo() { panic!("Coś poszło nie tak"); }

Przykłady rzeczywistych błędów z powodu nieznajomości zagadnienia


Historia

W mikrousługach do przetwarzania obrazów deweloper użył panic! do obsługi wszystkich nieprzewidzianych sytuacji. Prowadziło to do awaryjnego zakończenia usługi przy każdej błędzie zamiast zwrócenia poprawnej odpowiedzi HTTP klientowi z szczegółami błędu.


Historia

W jednym narzędziu CLI użyto unwrap() do całego wejścia/wyjścia, nie obsługując możliwych błędów. W rezultacie w przypadku błędu systemu plików program po prostu kończył działanie bez jakiegokolwiek komunikatu lub diagnostyki.


Historia

W usłudze analitycznej próbowano użyć Option dla każdego najmniejszego błędu, pozbawiając się informacji o samych błędach, co utrudniało debugowanie. Po przejściu na Result z błędami w enumach łatwiej było znajdować i naprawiać błędy.