Оператор спроб

Помилки виконання, такі як відмова у з'єднанні або не знайдено файл, обробляються за допомогою типу Result, але зіставлення цього типу для кожного виклику може бути громіздким. Оператор спроби ? використовується для повернення помилок користувачеві. Він дозволяє перетворити звичайний оператор

match some_expression {
    Ok(value) => value,
    Err(err) => return Err(err),
}

у набагато простіше

some_expression?

Ми можемо використовувати це, щоб спростити наш код обробки помилок:

use std::io::Read;
use std::{fs, io};

fn read_username(path: &str) -> Result<String, io::Error> {
    let username_file_result = fs::File::open(path);
    let mut username_file = match username_file_result {
        Ok(file) => file,
        Err(err) => return Err(err),
    };

    let mut username = String::new();
    match username_file.read_to_string(&mut username) {
        Ok(_) => Ok(username),
        Err(err) => Err(err),
    }
}

fn main() {
    //fs::write("config.dat", "alice").unwrap();
    let username = read_username("config.dat");
    println!("ім'я користувача або помилка: {username:?}");
}
This slide should take about 5 minutes.

Спростіть функцію read_username до використання ?.

Ключові моменти:

  • Змінна username може мати значення Ok(string) або Err(error).
  • Використовуйте виклик fs::write, щоб перевірити різні сценарії: відсутність файлу, порожній файл, файл з іменем користувача.
  • Зверніть увагу, що main може повертати Result<(), E>, якщо вона реалізує std::process:Termination. На практиці це означає, що E реалізує Debug. Виконуваний файл виведе варіант Err і поверне ненульовий статус виходу у разі помилки.