10-及早返回和运算符?
6.4 及早返回和运算符“?”
这是我们与Result类型交互时非常常见的另一种模式。它的运行机制如下:当我们获得一个成功值时,希望立即提取它;当我们获得一个错误值时,希望提前返回,并将错误传播给调用方。为了说明这种模式,我们将使用以下代码段,它使用常见的match表达式来处理Result类型:
// result_common_pattern.rs
use std::string::FromUtf8Error;
fn str_upper_match(str: Vec<u8>) -> Result<String, FromUtf8Error> {
let ret = match String::from_utf8(str) {
Ok(str) => str.to_uppercase(),
Err(err) => return Err(err)
};
println!("Conversion succeeded: {}", ret);
Ok(ret)
}
fn main() {
let invalid_str = str_upper_match(vec![197, 198]);
println!("{:?}", invalid_str);
}
运算符“?”抽象了这种模式,这使我们能够以一种更简洁的方式编写bytes_to_str方法:
// using_question_operator.rs
use std::string::FromUtf8Error;
fn str_upper_concise(str: Vec<u8>) -> Result<String, FromUtf8Error> {
let ret = String::from_utf8(str).map(|s| s.to_uppercase())?;
println!("Conversion succeeded: {}", ret);
Ok(ret)
}
fn main() {
let valid_str = str_upper_concise(vec![121, 97, 89]);
println!("{:?}", valid_str);
}
如果你有一系列Result/Option的返回方法调用,那么此运算符的效果会更好,其中任何一个运算符失败都意味着整体失败。例如,我们可以编写创建文件,并写入文件的整体操作,如下所示:
let _ = File::create("foo.txt")?.write_all(b"Hello world!")?;
它几乎可以作为try!宏的替代品,在“?”之前所做的事情已经由编译器提供相应的实现。现在“?”是它的替代品,不过也有一些规划可以让它变得更通用,让它适用于其他情况。
温馨提示:main函数还允许用户返回Result类型。具体来说,它允许你返回实现Termination特征的类型。这意味着我们也可以按如下方式编写main函数:
// main_result.rs
fn main() -> Result<(), &'static str> {
let s = vec!["apple", "mango", "banana"];
let fourth = s.get(4).ok_or("I got only 3 fruits")?;
Ok(())
}
接下来,我们将讨论不可恢复异常。