Одна из причин, почему Rust ценят за надёжность, — явная работа с ошибками. Вместо исключений язык предлагает два ключевых типа: `Option` и `Result`. Это делает код предсказуемым, а ошибки — контролируемыми.
Когда использовать `Option`
`Option<T>` нужен, когда значение может отсутствовать, и это нормальная часть логики программы.
- `Some(T)` — значение есть
- `None` — значения нет
Пример: поиск элемента в коллекции, чтение необязательного поля, получение первого символа строки.
fn find_user(id: u32) -> Option<String> {
if id == 1 {
Some("Alice".to_string())
} else {
None
}
}
Здесь `None` не означает сбой — просто пользователь не найден.
Когда использовать `Result`
`Result<T, E>` нужен, когда операция может завершиться ошибкой.
- `Ok(T)` — успех
- `Err(E)` — ошибка
Типичный пример — чтение файла, сетевой запрос, парсинг числа.
use std::fs;
fn read_config() -> Result<String, std::io::Error> {
fs::read_to_string("config.toml")
}
Если файл не найден или нет прав доступа, функция вернёт `Err`.
Главное различие
- `Option` — нет значения, но это ожидаемо
- `Result` — произошла ошибка, которую нужно обработать
Это важный принцип проектирования API в Rust: не путать “ничего не найдено” и “что-то сломалось” 🔍
Как обрабатывать `Option` и `Result`
Самый читаемый способ — `match`:
match read_config() {
Ok(data) => println!("Файл загружен: {}", data),
Err(e) => eprintln!("Ошибка: {}", e),
}
Но в реальном коде часто используют более короткие методы:
- `unwrap()` — извлекает значение, но вызывает panic при ошибке
- `expect("...")` — то же, но с понятным сообщением
- `unwrap_or(...)` — значение по умолчанию
- `map(...)` — преобразование содержимого
- `and_then(...)` — цепочка операций
- `?` — удобная передача ошибки выше по стеку
Пример с `?`:
use std::fs;
fn load() -> Result<String, std::io::Error> {
let text = fs::read_to_string("config.toml")?;
Ok(text)
}
Оператор `?` сокращает шаблонную обработку и делает код чище ✨
Частые ошибки новичков
- Злоупотребление `unwrap()` в продакшене
- Использование `Option` там, где нужна причина ошибки
- Игнорирование типа ошибки в `Result`
- Смешивание бизнес-логики и аварийных `panic!`
Практическое правило
- Используйте `Option`, если отсутствие значения — нормальный сценарий
- Используйте `Result`, если важно понять причину сбоя
- Применяйте `?`, чтобы не писать лишний шаблонный код
- Оставляйте `unwrap()` в прототипах, тестах или там, где ошибка действительно невозможна 🛠️
Итог: `Option` и `Result` — основа безопасной разработки на Rust. Они заставляют явно думать о пограничных случаях, а это напрямую влияет на качество, стабильность и сопровождаемость кода 🚀
👀 Ниже по ленте — мягко рекомендую посмотреть подборку каналов про IT: там много полезного по Rust, backend и инженерным практикам.