Result比Option类型包含的内容更丰富,可以描述各种可能的错误而不是仅仅返回None。
即:Result<T,E>可以返回下面两种结果:
- Ok(T):有正确的结果返回
- Err(E):返回错误E
简而言之:期待返回的结果是Ok,意料之外的结果是Err。
和Option一样,Result也有许多与之配合的方法。例如:unwrap()要么返回元素T,要么返回错误E。为了处理这些情况,Result和Option有许多操作符是重复的。
在Rust编程中,你可以会遇到返回Result类型的方法,例如parse(),它也许有时会不能将字符串成功的解析为某种类型,因此parse()会返回Result来包含这种可能性。
下面让我们看看parse()成功和失败的示例:
fn multiply(first_number_str: &str, second_number_str: &str) -> i32 {
// Let's try using `unwrap()` to get the number out. Will it bite us?
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()抛成了panic并退出了程序,我们只能看到一条令人恼火的错误消息。
为了改善这种情况,我们应该指定更加具体的返回类型,来考虑到这种情况,并显式的处理这种情况。
在主函数中使用Result类型
如果显式的指定了main的返回类型为Result,也是可以的。之前的main函数如下所示:
fn main() {
println!("Hello World!");
}
然而,主函数也可以指定返回值为Result。如果在主函数中发生了错误,它将会返回错误代码并输出错误的调试信息。下面的示例展示了主函数返回Result类型:
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(())
}