Обработка ошибок в Rust: Result и Option

Мы просто и по делу рассказываем про ИИ-инструменты для работы: сравнения, пошаговые гайды, бесплатные альтернативы и реальные сценарии применения. Помогаем выбрать между ChatGPT, Gemini, Claude, локальными моделями и десятками узкоспециализированных сервисов — от дизайна и HR до аналитики и SEO. Меньше хайпа, больше практики и экономии времени каждый день.

Rustoptionresult

Одна из причин, почему 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 и инженерным практикам.

🗣 Подборки каналов
🧠 Каталог ботов и приложений
🗺 Навигация

Читайте так же