当前位置:嗨网首页>书籍在线阅读

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(())
}

接下来,我们将讨论不可恢复异常。