【问题标题】:How do I idiomatically unwrap Rust errors with functions rather than closures?我如何习惯性地用函数而不是闭包来解开 Rust 错误?
【发布时间】:2021-11-02 02:22:35
【问题描述】:

我在 Rust 中干净利落地处理错误。假设我有一个使用Box<dyn Error> 传播多种错误类型的函数。为了打开并处理错误,我正在执行以下操作:

fn main() {
    let json =
        get_json_response(format!("{}{}", BASE_URL, LOGIN_URL).as_str()).unwrap_or_else(|e| {
            eprintln!("Error: failed to get: {}", e);
            std::process::exit(1);
        });
}

fn get_json_response(url: &str) -> Result<Value, Box<dyn Error>> {
    let resp = ureq::get(url)
        .set("Authorization", format!("Bearer {}", API_TOKEN).as_str())
        .call()?
        .into_json()?;
    Ok(resp)
}

这很好用。但是,如果我多次调用 get_json_response(),那么一遍又一遍地包含同一个闭包会变得很混乱。

我的解决方案是将其更改为:

use serde_json::Value;
use std::error::Error;
use ureq;

fn main() {
    let json =
        get_json_response(format!("{}{}", BASE_URL, LOGIN_URL).as_str()).unwrap_or_else(fail);
}

fn fail(err: Box<dyn Error>) -> ! {
    eprintln!("Error: failed to get: {}", err);
    std::process::exit(1);
}

这不起作用,因为unwrap_or_else() 期望返回Value,而不是返回任何!。我可以作弊并将fail()的返回值更改为-&gt; Value,并在exit(1)之后添加Value::Null。它有效,但感觉不对(并抱怨)。

我也可以使用unwrap_or_else(|e| fail(e)),这还不错。

有没有一种惯用的方法来处理这个问题?

【问题讨论】:

  • @user4815162342 哎呀,你说得对,我把它弄反了。 .expect() 应该这样做。
  • 如果结果为None@Herohtar expect() 会恐慌,而 OP 希望控制进程退出的方式。
  • @user4815162342 他们有吗?他们并没有说他们不想惊慌,尽管我想这是可以假设的。但是,建议在大多数情况下恐慌,根据this answer
  • @Herohtar 我不能代表 OP,但现有代码专门使用 unwrap_or_else 来避免恐慌是一个强烈的暗示。建议总是恐慌的答案忽略了您有时希望更好地控制错误消息和退出状态,我希望这里就是这种情况。
  • 虽然! 可以强制转换为任何T,但fn()-&gt;! 不能强制转换为fn()-&gt;T。这就是 lambda 有效但函数无效的原因。

标签: rust error-handling


【解决方案1】:

作为@kmdreko 的pointed out,您的代码无法编译,因为虽然! 可以强制转换为任何T,但fn() -&gt; ! 不能强制转换为fn() -&gt; T

要解决上述问题,您可以声明fail() 以返回Value,并实际返回std::process::exit(1) 的“值”。省略分号会将! 强制转换为Value,并且您不必用Value::Null 作弊:

fn main() {
    let _json = get_json_response("...").unwrap_or_else(fail).as_str();
}

fn fail(err: Box<dyn Error>) -> Value {
    eprintln!("Error: failed to get: {}", err);
    std::process::exit(1)
}

Playground

【讨论】:

猜你喜欢
  • 2019-06-13
  • 2017-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多