Этот вопрос проверяет понимание обработки ошибок с помощью Result и кастомных типов ошибок, а также использования оператора ? для упрощения обработки ошибок.
Пользовательские типы ошибок (enum) позволяют точно описывать различные сценарии ошибок, а комбинация Result с ? обеспечивает компактную и читаемую обработку ошибок. Это помогает передавать ошибки через стек вызовов и обрабатывать их на верхнем уровне.
Пользовательские типы ошибок:
Создайте enum, чтобы описать разные виды ошибок. Это упрощает диагностику и обработку:
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
#[error("Ошибка ввода-вывода: {0}")]
IoError(#[from] std::io::Error),
#[error("Некорректный ввод: {0}")]
InvalidInput(String),
}Комбинация с Result:
Функции возвращают Result<T, MyError>, где T — успешный результат, а MyError описывает возможные ошибки:
fn read_file(filename: &str) -> Result<String, MyError> {
let mut content = String::new();
let mut file = std::fs::File::open(filename)?;
file.read_to_string(&mut content)?;
Ok(content)
}Оператор ?:
Оператор ? автоматически возвращает ошибку, если она произошла, делая код чище:
fn process_file(filename: &str) -> Result<(), MyError> {
let content = read_file(filename)?; // Пропуск ошибки вверх
println!("Содержимое файла: {}", content);
Ok(())
}Обработка ошибок на верхнем уровне:
Используйте match или синтаксис main -> Result для обработки:
fn main() -> Result<(), MyError> {
match process_file("data.txt") {
Ok(_) => println!("Файл успешно обработан!"),
Err(e) => eprintln!("Ошибка: {}", e),
}
Ok(())
}Преимущества:
Читабельность: ? избегает вложенности.
Гибкость: Пользовательские ошибки позволяют точно описать причину.
Эффективная обработка: Ошибки легко передаются по стеку вызовов.