0

当多行相互跟随时,我想在处理错误时减少样板代码。我有以下代码,工作,但我想知道是否可以减少它:

let mut sto = match Storage::new() {
    Ok(v) => v,
    Err(e) => {
        // if needed the error message could be the same as in the next
        // bloc, but I want to stop the process here
        error!("Failed to open the connection.");
        return Err(e);
    },
};

// If Ok(), do not care about
if let Err(e) = sto.set("key", item) {
    error!("Failed to save the item.");
    return Err(e);
}

注意:error!宏是一个记录器宏

有可能有这样的东西吗?

if let Err(e) = Storage::new().MAGICAL_FUNC().set("key", item) {
    error!("Failed to save the item.");
    return Err(e);
}

我的搜索:

  • unwrap因为 MAGICAL_FUNC 会导致恐慌,所以它是不可恢复的。
  • 与闭包一起使用and_then将防止if let“捕获”闭包Err中的set函数。
  • map_err不会“解包” Ok()。所以应该在“unwrap”中添加一个新行。

编辑:精确的error!宏行为

➡️解决方案:接受Masklinn的答案+评论

4

1 回答 1

2

您可以使用?运算符使您的错误处理代码更简洁。例子:

struct Storage;

enum Error {
    ConnectionFailure,
    SaveFailure,
}

impl Storage {
    fn new() -> Result<Self, Error> {
        Ok(Storage)
        // but could possible return
        // Err(Error::ConnectionFailure)
    }
    fn set<T>(&self, key: &'static str, item: T) -> Result<(), Error> {
        Ok(())
        // but could possible return
        // Err(Error::SaveFailure)
    }
}

fn save_item<T>(key: &'static str, item: T) -> Result<(), Error> {
    let storage = Storage::new()?;
    storage.set(key, item)?;
    Ok(())
}

fn main() {
    match save_item("key", 123) {
        Err(Error::ConnectionFailure) => {
            // handle connection failure error
        },
        Err(Error::SaveFailure) => {
            // handle save failure error
        },
        _ => {
            // everything went fine catch-all
        }
    }
}

操场

也可以看看:

于 2020-09-23T23:08:49.267 回答