anyhow
灵活的应用错误处理
anyhow 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
灵活的应用程序错误
在应用程序代码中,您通常只希望错误携带上下文向上传递,而不想为每种错误分别定义带类型的枚举。anyhow 软件包正好为此提供了一个简单的错误类型。
添加 anyhow
将其添加为依赖项。它与 thiserror 配合良好:库使用 thiserror,二进制程序使用 anyhow。
[dependencies]
anyhow = "1.0"anyhow::Result 别名
anyhow::Result<T> 是 Result<T, anyhow::Error> 的简写。Error 类型可以容纳任何实现了 std::error::Error 的错误。
use anyhow::Result;
fn load() -> Result<String> {
let text = std::fs::read_to_string("config.txt")?;
Ok(text)
}自动转换
? 运算符会自动将任何标准错误转换为 anyhow::Error,因此您可以自由混用不同的错误类型。
use anyhow::Result;
fn parse_file(path: &str) -> Result<i32> {
let text = std::fs::read_to_string(path)?; // io error
let n: i32 = text.trim().parse()?; // parse error
Ok(n)
}添加上下文
.context() 方法会为错误附加一条易于理解的消息,在发生失败时构建出清晰的错误链。
use anyhow::{Context, Result};
fn read_config(path: &str) -> Result<String> {
let text = std::fs::read_to_string(path)
.context("failed to read config file")?;
Ok(text)
}延迟添加上下文
在构建消息的成本较高或需要运行时数据时,请使用 with_context;该闭包只会在发生错误时执行。
use anyhow::{Context, Result};
fn open(path: &str) -> Result<String> {
std::fs::read_to_string(path)
.with_context(|| format!("could not open {path}"))
}创建临时错误
anyhow! 宏会根据消息构建错误,而 bail! 宏会携带该错误提前返回。
use anyhow::{anyhow, bail, Result};
fn check(age: i32) -> Result<()> {
if age < 0 {
bail!("age cannot be negative");
}
if age > 150 {
return Err(anyhow!("age {age} is implausible"));
}
Ok(())
}使用 ensure!
ensure! 类似于 assert!,但它会返回错误,而不是触发恐慌。
use anyhow::{ensure, Result};
fn divide(a: i32, b: i32) -> Result<i32> {
ensure!(b != 0, "division by zero");
Ok(a / b)
}main 中的 anyhow
让 main 返回 anyhow::Result<()>,这样发生失败时就会打印格式良好的错误链。
use anyhow::Result;
fn main() -> Result<()> {
let text = std::fs::read_to_string("data.txt")?;
println!("{text}");
Ok(())
}检查原因
尽管 anyhow::Error 是不透明的,您仍然可以检查它。需要根据具体错误类型进行分支处理时,downcast_ref 可以恢复具体的错误类型。
use anyhow::Result;
fn report(err: anyhow::Error) {
if let Some(io) = err.downcast_ref::<std::io::Error>() {
println!("io error: {io}");
} else {
println!("other error: {err}");
}
}thiserror 与 anyhow
经验法则:
- thiserror — 用于库,以及调用方需要匹配的带类型错误
- anyhow — 用于应用程序,只需携带上下文向上传递错误
您可以使用 ?,将 thiserror 错误无缝转换为 anyhow。
快速检查
anyhow 的哪个方法会在错误传播时为其附加描述性消息?
回顾
您已经学习了 anyhow 软件包:
anyhow::Result<T>使用一种灵活的错误类型?会自动转换任何标准错误.context()/with_context()会添加易于理解的消息anyhow!、bail!和ensure!可以创建错误- 最适合应用程序(二进制程序)代码
常见问题解答
「anyhow」课时是免费的吗?
是的 — 「anyhow」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「anyhow」这节课中我会学到什么?
灵活的应用错误处理 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「anyhow」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。