2.7 `anyhow`
07-anyhow — Comprehensive Rust
译文 · 基于 Comprehensive Rust
原文链接: https://google.github.io/comprehensive-rust/error-handling/anyhow.html
2.7 anyhow
anyhow crate 提供功能丰富的错误类型,支持附带额外上下文信息,从而可以对程序在出错前正在做什么给出语义化追踪。
它可以与 thiserror 的便利宏结合使用,避免为自定义错误类型显式写出 trait 实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| // Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
use anyhow::{Context, Result, bail};
use std::fs;
use std::io::Read;
use thiserror::Error;
#[derive(Clone, Debug, Eq, Error, PartialEq)]
#[error("Found no username in {0}")]
struct EmptyUsernameError(String);
fn read_username(path: &str) -> Result<String> {
let mut username = String::with_capacity(100);
fs::File::open(path)
.with_context(|| format!("Failed to open {path}"))?
.read_to_string(&mut username)
.context("Failed to read")?;
if username.is_empty() {
bail!(EmptyUsernameError(path.to_string()));
}
Ok(username)
}
fn main() {
//fs::write("config.dat", "").unwrap();
match read_username("config.dat") {
Ok(username) => println!("Username: {username}"),
Err(err) => println!("Error: {err:?}"),
}
}
|
讲师备注anyhow::Error 本质上是对 Box<dyn Error> 的包装。因此它通常也不适合作为库的公共 API,但在应用程序中被广泛使用。anyhow::Result<V> 是 Result<V, anyhow::Error> 的类型别名。anyhow::Error 提供的功能对 Go 开发者可能很熟悉:行为类似 Go 的 error 类型,而 Result<T, anyhow::Error> 很像 Go 的 (T, error)(约定上这对值中只有一个元素有意义)。anyhow::Context 是为标准库的 Result 和 Option 实现的 trait。需要 use anyhow::Context,才能在这些类型上启用 .context() 和 .with_context()。
延伸阅读
anyhow::Error 支持向下转换(downcast),类似 std::any::Any;若需要,可用 Error::downcast 取出内部具体的错误类型加以检查。