У меня есть собственное перечисление ошибок, которое включает в себя пару распространенных ошибок в моем коде:
pub enum ParseError {
Io(io::Error),
Parse(serde_json::error::Error),
FileNotFound(PathBuf, io::Error),
}
Это перечисление реализует трейт Display (по мере необходимости):
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::Io(io_error) => write!(f, "{}", io_error),
ParseError::Parse(parse_error) => write!(f, "{}", parse_error),
ParseError::FileNotFound(file, err) => {
write!(f, "Could not open file {}: {}", file.to_string_lossy(), err)
}
}
}
}
Обратите внимание, что для "пользовательской ошибки" FileNotFound мне нужно написать! как ошибка, так и имя файла, которое с ней связано. Однако позже, когда я обрабатываю эту ошибку, мне нужно снова напечатать как имя файла, так и ошибку:
match my_function(arg1, arg2) {
Ok(_) => (),
Err(error) => match error {
Io(err) => //do stuff,
},
Parse(err) => //do stuff
},
FileNotFound(file, err) => {
println!("Can't find file '{}': {}", file.to_string_lossy(), err)
}
Без форматирования имени файла и ошибки в Match, Rust просто печатает общую ошибку (в данном случае «Система не может найти указанный файл. (Ошибка ОС 2)».
Мой вопрос: почему требуется сначала реализовать отображение и форматирование ошибки, если требуется отформатировать ее снова, чтобы распечатать/использовать ее?
Повторно форматировать не требуется. Это особенно полезно, когда вы не используете match
на нем, но когда вы это делаете, вы можете использовать @
для создания привязки ко всему элементу:
match my_function(arg1, arg2) {
Ok(_) => (),
Err(error) => match error {
Io(err) => { //do stuff,
}
Parse(err) => { //do stuff
}
error @ FileNotFound(..) => {
println!("{error}");
}
},
}
Вы также можете создать ошибку на месте:
FileNotFound(file, err) => {
println!("{}", FileNotFound(file, err));
}
Еще одна распространенная вещь — использовать всеобъемлющее действие для выполнения действия над всеми несопоставленными ошибками:
error => {
println!("{error}");
}