Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

核心宏

这一节我们来看看 anyhow 提供的三个核心宏:anyhow!bail!ensure!

它们的作用是让你在代码中产生错误时,写起来像 println! 一样爽快。


1、anyhow!:快速创建错误对象

有时候你需要手动创建一个错误,而不是从别的函数传过来。anyhow! 支持字符串格式化,生成的类型是 anyhow::Error

use anyhow::{anyhow, Result};
fn get_username(id: u32) -> Result<String> {
    if id == 404 {
        // 创建一个一次性的、没有特定类型的错误
        return Err(anyhow!("找不到 ID 为 {} 的用户", id));
    }
    Ok("Alice".to_string())
}

2、bail!:错误处理的“提前离场”

bail!return Err(anyhow!(...)) 的缩写。它是代码中最常用的宏,用于在检测到异常时立即退出当前函数。

对比效果:

  • 普通写法: return Err(anyhow!("权限不足"));
  • 使用 bail! bail!("权限不足");
use anyhow::{bail, Result};
fn login(password: &str) -> Result<()> {
    if password != "123456" {
        bail!("密码错误,登录失败!"); // 简洁明了
    }
    println!("登录成功");
    Ok(())
}

3、ensure!:带条件的错误拦截

ensure! 就像是 assert!(断言)的温和版本。

  • assert!:如果条件不成立,程序直接 Panic(崩溃)。
  • ensure!:如果条件不成立,函数 返回 Err(优雅退出)。

它非常适合用来做输入校验。

use anyhow::{ensure, Result};
fn set_age(age: u8) -> Result<()> {
    // 如果 age <= 150 不成立,则返回 Err
    ensure!(age <= 150, "年龄 {} 显然不合逻辑", age);
    println!("年龄设置为: {}", age);
    Ok(())
}

4、这三个宏该选哪个?

为了帮你快速决策,可以参考下面这个简单的逻辑流:

  • 只是想造个错误传给别人? → 用 anyhow!
  • 遇到错误想直接返回中止函数? → 用 bail!
  • 检查一个条件,如果不满足就返回错误? → 用 ensure!

5、小结

类似的标准宏返回值语义
anyhow!format!anyhow::Error创建一个错误。
bail!panic!Result<_, Error>立即报错退出。
ensure!assert!Result<_, Error>满足条件继续,否则报错。

提示: > 所有的宏都支持类似 println! 的参数格式化,比如 bail!("错误码: {}", code),非常方便。