at5*_*321 24 error-handling rust
我正在使用Anyhow并有一个返回的函数anyhow::Result。在该函数中,我想“解开”一个选项,以便如果选项值为None,则返回带有特定错误消息的错误。这就是我所做的:
let o: Option<i32> = ...;
let v: i32 = o.ok_or_else(|| anyhow!("Oh, boy!"))?;
// here I need v only
Run Code Online (Sandbox Code Playgroud)
ok_or_else()出于ok_or()性能原因,我使用了 not 。
我通常对此表示同意,但想知道这是否是做我想做的事情的最简单(最简洁)的方法(不牺牲性能)?
egg*_*yal 38
use anyhow::{Context, Result};
fn _foo(o: Option<i32>) -> Result<i32> {
let v = o.context("Oh, boy!")?;
Ok(v)
}
Run Code Online (Sandbox Code Playgroud)
这个问题越来越受欢迎,所以我决定,作为 Eggyal 答案的补充,描述该context()方法如何在“幕后”实际工作,以便它可以方便地用于Option这样的值:some_opt.context("some error info here")?。
context()首先,无论如何Context公开一个具有方法的公共特征context():
pub trait Context<T, E>: Sealed {
fn context<C>(self, context: C) -> Result<T, Error>
where C: Display + Send + Sync + 'static;
Run Code Online (Sandbox Code Playgroud)
该Context特征是为了实现的,Option并且实现如下所示:
impl<T> Context<T, Infallible> for Option<T> {
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(Error::from_display(context, backtrace!())),
}
}
Run Code Online (Sandbox Code Playgroud)
内部的实现from_display()有点复杂。它利用不安全Error::construct()并返回一个anyhow::Error值。
with_context()Context还定义了一个类似的方法with_context(),可用于提供延迟评估的上下文(仅当错误实际发生时)。例子:
some_opt.with_context(|| format!("User {u} has no money"))?
Run Code Online (Sandbox Code Playgroud)
除了“懒惰”之外, 的实现本质with_context()上与 的实现相同context()。
ok_or_else(|| anyhow!("..."))值得注意的是,在anyhow生成的堆栈(返回)跟踪中(当使用nightly或features = ["backtrace"]时),如果我们使用表达式ok_or_else(|| anyhow!("...")),顶部会有一个额外的元素,如下所示:
Stack backtrace:
0: anyhow::error::<impl anyhow::Error>::msg
Run Code Online (Sandbox Code Playgroud)
例如,如果我们使用bail!or ,也会发生同样的情况。ensure!
当我们使用context()or时context_with(),堆栈跟踪中没有这样的行。
| 归档时间: |
|
| 查看次数: |
9012 次 |
| 最近记录: |