在Rust中优雅地向上级传递Result<>中的错误信息

2023-10-18 10:46:03 浏览数 (1)

在Rust中,我们会经常使用Result<xxxx,xxxx>来返回正确结果和错误信息。但是,在这样的需求下,我们会遇到一个麻烦事:函数A内部要调用多个函数,并且只要其中某个步骤出错,当前函数A就直接返回这个错误信息。

在上面这个场景下,我们会编写许多这样的代码:

代码语言:javascript复制
use std::fs::File;
use std::io::prelude::*;
use std::io;

struct Info {
    name: String,
    age: i32,
    rating: i32,
}

fn write_info(info: &Info) -> io::Result<()> {
    // Early return on error
    let mut file = match File::create("my_best_friends.txt") {
           Err(e) => return Err(e),
           Ok(f) => f,
    };
    if let Err(e) = file.write_all(format!("name: {}n", info.name).as_bytes()) {
        return Err(e)
    }
    if let Err(e) = file.write_all(format!("age: {}n", info.age).as_bytes()) {
        return Err(e)
    }
    if let Err(e) = file.write_all(format!("rating: {}n", info.rating).as_bytes()) {
        return Err(e)
    }
    Ok(())
}

冗长的错误处理代码显得非常不雅观,为了解决这个问题,我们可以使用“问号运算符”,来简化这个流程:

代码语言:javascript复制
use std::fs::File;
use std::io::prelude::*;
use std::io;

struct Info {
    name: String,
    age: i32,
    rating: i32,
}

fn write_info(info: &Info) -> io::Result<()> {
    let mut file = File::create("my_best_friends.txt")?;
    // Early return on error
    file.write_all(format!("name: {}n", info.name).as_bytes())?;
    file.write_all(format!("age: {}n", info.age).as_bytes())?;
    file.write_all(format!("rating: {}n", info.rating).as_bytes())?;
    Ok(())
}

在上述代码中,以“?”结尾的表达式,将会自动unwrap Ok()的成功值,如果Result<>是Err,那就会自动吧把这个Err向上传递,也就是,当前函数直接return这个错误值。

本文引用:https://doc.rust-lang.org/std/result/

0 人点赞