В Rust нет привычных исключений (exceptions) как в Java или C++; вместо этого используются типы-обёртки Result и Option для возвращения ошибок.
Result<T, E> — хранит либо значение (Ok(T)), либо ошибку (Err(E)). Его обычно применяют для операций, которые могут не выполниться корректно (например, файловый ввод-вывод).
Option<T> — для опциональных значений: либо Some(T), либо None, без информации об ошибке. Пример:
fn divide(x: f64, y: f64) -> Option<f64> { if y == 0.0 { None } else { Some(x / y) } }
В Rust нет исключений в стиле try/catch, чтобы обеспечить прозрачный, управляемый поток ошибок и не требовать сборщика мусора или unwind-движка для поддержания исключений.
Почему panic! нельзя использовать для обычной обработки ошибок?
Ответ: panic! завершает поток исполнения, не даёт возможности восстановиться, приводит к unwinding/abort. Если же ошибки возвращаются через Result, вызывающая сторона может их обработать. Пример:
fn foo() -> Result<(), String> { Err("Smth went wrong".to_string()) } // вместо fn foo() { panic!("Smth went wrong"); }
История
В микросервисе для обработки изображений разработчик использовал
panic!для обработки всех нештатных ситуаций. Это приводило к аварийному завершению сервиса при любой ошибке вместо возвращения корректного HTTP-ответа client'у с деталями ошибки.
История
В одном инструменте для CLI использовали
unwrap()для всего ввода-вывода, не обрабатывая возможные ошибки. В результате при ошибке файл-системы программа просто завершалась без какого-либо сообщения или диагностики.
История
В сервисе аналитики попытались использовать Option для каждой малейшей ошибки, лишившись информации о самих ошибках, затруднив отладку. После перехода на Result с ошибками-энумами стало проще находить и исправлять баги.