前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Rust每周一库】anyhow和thiserror - 错误处理库

【Rust每周一库】anyhow和thiserror - 错误处理库

作者头像
MikeLoveRust
发布2020-04-21 15:09:20
3.2K0
发布2020-04-21 15:09:20
举报

前言

之前我们借助讲解failure库,详细说明的Rust错误处理的哲学,这有助于我们理解今天的主题,anyhow和thiserror

Anyhow提供了一个anyhow::Error trait(有点类似failure::Error)。而得益于std::error::Error所做的修改,它anyhow::Error与std::error::Error兼容的。也就是说,对于自定义的错误类型,只需要实现std::error::Error即可。这对于程序的兼容性是一大利好,也因此failure库被日渐废弃。而thiserror正是方便大家为自定义的错误使用宏实现std::error::Error而设计的。

依赖

代码语言:javascript
复制
[dependencies]
anyhow = "1.0"
thiserror = "1.0"
Anyhow用法

在需要返回Result的地方,使用Result<T, anyhow::Error>或者等价的anyhow::Result<T>,就可以利用抛出任何类型实现了std::error::Error的错误

代码语言:javascript
复制
use anyhow::Result;

fn get_cluster_info() -> Result<ClusterMap> {
    let config = std::fs::read_to_string("cluster.json")?;
    let map: ClusterMap = serde_json::from_str(&config)?;
    Ok(map)
}
还可以给错误加上上下文(context)
代码语言:javascript
复制
use anyhow::{Context, Result};

fn main() -> Result<()> {
    ...

    let content = std::fs::read(path)
        .with_context(|| format!("Failed to read instrs from {}", path))?;
    ...
}
Error: Failed to read instrs from ./path/to/instrs.json
这样就会在发送错误时看到上下文
代码语言:javascript
复制
Error: Failed to read instrs from ./path/to/instrs.json

Caused by:
    No such file or directory (os error 2)
anyhow宏可以基于错误字符串产生一个anyhow::Error(类似于failure中的format_err宏)
代码语言:javascript
复制
return Err(anyhow!("Missing attribute: {}", missing));
thiserror用法
代码语言:javascript
复制
use thiserror::Error;

#[derive(Error, Debug)]
pub enum DataStoreError {
    #[error("data store disconnected")]
    Disconnect(#[from] io::Error),
    #[error("the data for key `{0}` is not available")]
    Redaction(String),
    #[error("invalid header (expected {expected:?}, found {found:?})")]
    InvalidHeader {
        expected: String,
        found: String,
    },
    #[error("unknown data store error")]
    Unknown,
}
实际上,只要为struct或者每个成员提供#[error("...")],那么就会实现Display,具体语法如下
  • #[error("{var}")] ⟶ write!("{}", self.var)
  • #[error("{0}")] ⟶ write!("{}", self.0)
  • #[error("{var:?}")] ⟶ write!("{:?}", self.var)
  • #[error("{0:?}")] ⟶ write!("{:?}", self.0)

通过sourcebacktrace字段(或者#[source]#[backtrace])可以指定source()和backtrace()的返回。还可以通过#[from]实现为source实现From

代码语言:javascript
复制
#[derive(Error, Debug)]
pub enum MyError {
    Io {
        #[from]
        source: io::Error,
        backtrace: Backtrace,
    },
}
小结

通过anyhow和thiserror,错误处理是不是变得轻松多了呢?直接支持std::error:Error,真香!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 依赖
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档