Введение
В этом лабе мы будем изучать тип Result в Rust, который предоставляет способ обрабатывать потенциальные ошибки вместо возможного отсутствия значения, как это делает тип Option. Тип Result может иметь два результата - Ok(T) для успешного результата с элементом T и Err(E) для ошибки с элементом E. Мы увидим, как использовать Result в примерах кода и как его можно использовать в качестве возвращаемого типа функции main для обработки ошибок и предоставления более конкретного сообщения об ошибке.
Примечание: Если в лабе не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать
main.rs, скомпилировать и запустить его с помощьюrustc main.rs &&./main.
Result
Result - это более богатый вариант типа Option, который описывает возможную ошибку вместо возможного отсутствия.
То есть, Result<T, E> может иметь один из двух результатов:
Ok(T): Найден элементTErr(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(())
}
Резюме
Поздравляем! Вы завершили лабу по Result. Вы можете практиковаться в других лабах в LabEx, чтобы улучшить свои навыки.