【Rust自学】11.3. 自定义错误信息

📅 2026/7/23 18:53:32 👁️ 阅读次数 📝 编程学习
【Rust自学】11.3. 自定义错误信息

11.3 自定义错误信息

11.3.1. 添加错误信息

在 11.2. 断言(Assert) 中我们学习了assert!assert_eq!assert_ne!这三个宏,而这篇文章讲的是它们的进阶用法。

这三个宏可以接收自定义错误信息,但这是可选项。如果添加了自定义信息,它们会和标准的失败信息一起打印出来:
- 对于assert!,第一个参数是必填的,自定义信息作为第二个参数。
- 对于assert_eq!assert_ne!,前两个参数是必填的,自定义信息作为第三个参数。

把自定义信息传进去之后,它会被传给format!宏来构建字符串。由于format!可以使用{}占位符,所以传进去的信息也可以使用占位符。

看个例子:

pub fn greeting(name: &str) -> String { format!("Hello {name}!") } #[cfg(test)] mod tests { use super::*; #[test] fn greeting_contains_name() { let result = greeting("Carol"); assert!(result.contains("Carol")); } }
  • greeting接收一个名为name的字符串切片参数,并返回由Helloname!拼接而成的字符串。
  • greeting_contains_name测试函数先把greeting("Carol")的返回值赋给result,然后在result上调用contains方法,检查result是否包含"Carol"

这段代码现在可以通过测试。

现在手动引入一个bug,修改greeting函数:

pub fn greeting(name: &str) -> String { format!("Hello!") } #[cfg(test)] mod tests { use super::*; #[test] fn greeting_contains_name() { let result = greeting("Carol"); assert!(result.contains("Carol")); } }

这样测试会失败:

$ cargo test Compiling greeter v0.1.0 (file:///projects/greeter) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.14s Running unittests src/lib.rs (target/debug/deps/greeter-647141eed08f233c) running 1 test test tests::greeting_contains_name ... FAILED failures: ---- tests::greeting_contains_name stdout ---- thread 'tests::greeting_contains_name' (455732) panicked at src/lib.rs:12:9: assertion failed: result.contains("Carol") note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::greeting_contains_name test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib`

不过失败信息只说在第12行第9列发生了恐慌,并没有提供更友好、更有用的信息。怎么办呢?添加自定义信息:

pub fn greeting(name: &str) -> String { format!("Hello!") } #[cfg(test)] mod tests { use super::*; #[test] fn greeting_contains_name() { let result = greeting("Carol"); assert!( result.contains("Carol"), "Greeting did not contain name, value was `{result}`" ); } }

输出:

$ cargo test Compiling greeter v0.1.0 (file:///projects/greeter) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.09s Running unittests src/lib.rs (target/debug/deps/greeter-647141eed08f233c) running 1 test test tests::greeting_contains_name ... FAILED failures: ---- tests::greeting_contains_name stdout ---- thread 'tests::greeting_contains_name' (456094) panicked at src/lib.rs:12:9: Greeting did not contain name, value was `Hello!` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::greeting_contains_name test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib`

可以看到,自定义信息出现在了错误输出里。这样的信息更有实际意义,也更容易找出错误原因。