Result
Result
- это более богатый вариант типа Option
, который описывает возможную ошибку вместо возможного отсутствия.
То есть, Result<T, E>
может иметь один из двух результатов:
Ok(T)
: Найден элемент T
Err(E)
: Найдена ошибка с элементом E
По соглашению, ожидаемый результат - это Ok
, в то время как неожиданный результат - это Err
.
Похоже на Option
, Result
имеет множество связанных с ним методов. Например, unwrap()
либо возвращает элемент T
, либо вызывает panic
. Для обработки случаев есть множество комбинаторов между Result
и Option
, которые перекрываются.
При работе с Rust вы, вероятно, встретите методы, которые возвращают тип Result
, например, метод parse()
. Не всегда удается преобразовать строку в другой тип, поэтому parse()
возвращает Result
, указывающий на возможную ошибку.
Посмотрим, что происходит, когда мы успешно и неуспешно parse()
строку:
fn multiply(first_number_str: &str, second_number_str: &str) -> i32 {
// Попробуем использовать `unwrap()` для извлечения числа. Не укусит ли нас это?
let first_number = first_number_str.parse::<i32>().unwrap();
let second_number = second_number_str.parse::<i32>().unwrap();
first_number * second_number
}
fn main() {
let twenty = multiply("10", "2");
println!("double is {}", twenty);
let tt = multiply("t", "2");
println!("double is {}", tt);
}
В случае неудачи parse()
оставляет ошибку для unwrap()
, чтобы вызвать panic
. Кроме того, panic
завершает нашу программу и выводит неприятное сообщение об ошибке.
Для улучшения качества нашего сообщения об ошибке мы должны быть более конкретными по отношению к возвращаемому типу и рассмотреть явную обработку ошибки.
Использование Result
в main
Тип Result
также может быть возвращаемым типом функции main
, если указать это явно. Обычно функция main
имеет следующий вид:
fn main() {
println!("Hello World!");
}
Однако main
также может иметь возвращаемый тип Result
. Если в функции main
возникает ошибка, она вернет код ошибки и выведет отладочное представление ошибки (с использованием трейта [Debug
]). Следующий пример показывает такой сценарий и затрагивает аспекты, рассмотренные в [следующем разделе].
use std::num::ParseIntError;
fn main() -> Result<(), ParseIntError> {
let number_str = "10";
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => return Err(e),
};
println!("{}", number);
Ok(())
}