diff --git a/src/basic/result-error/panic.md b/src/basic/result-error/panic.md index c9904844..f9dd0b7e 100644 --- a/src/basic/result-error/panic.md +++ b/src/basic/result-error/panic.md @@ -6,11 +6,43 @@ 上面的问题在真实场景会经常遇到,其实处理起来挺复杂的,让我们先做一个假设:文件读取操作发生在系统启动阶段。那么可以轻易得出一个结论,一旦文件读取失败,那么系统启动也将失败,这意味着该失败是不可恢复的错误,无论是因为文件不存在还是操作系统硬盘的问题,这些只是错误的原因不同,但是归根到底都是不可恢复的错误(梳理清楚当前场景的错误类型非常重要)。 -既然是不可恢复错误,那么一旦发生,只需让程序崩溃即可。对此,Rust 为我们提供了 `panic!` 宏,当调用执行该宏时,**程序会打印出一个错误信息,展开报错点往前的函数调用堆栈,最后退出程序**。 +对于这些严重到影响程序运行的错误,触发 `panic` 是很好的解决方式。在 Rust 中触发 `panic` 有两种方式:被动触发和主动调用,下面依次来看看。 -切记,一定是不可恢复的错误,才调用 `panic!` 处理,你总不想系统仅仅因为用户随便传入一个非法参数就崩溃吧?所以,**只有当你不知道该如何处理时,再去调用 panic!**. -## 调用 panic! +### 被动触发 +先来看一段简单又熟悉的代码: +```rust +fn main() { + let v = vec![1, 2, 3]; + + v[99]; +} +``` + +心明眼亮的同学立马就能看出这里发生了严重的错误 —— 数组访问越界,在其它编程语言中无一例外,都会报出严重的异常,甚至导致程序直接崩溃关闭。 + +而 Rust 也不例外,运行后将看到如下报错: +```shell +$ cargo run + Compiling panic v0.1.0 (file:///projects/panic) + Finished dev [unoptimized + debuginfo] target(s) in 0.27s + Running `target/debug/panic` +thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +上面给出了非常详细的报错信息,包含了具体的异常描述以及发生的位置,甚至你还可以加入额外的命令来看到异常发生时的堆栈信息,这个会在后面详细展开。 + +总之,类似的 `panic` 还有很多,而被动触发的 `panic` 是我们日常开发中最常遇到的,这也是 Rust 给我们的一种保护,毕竟错误只有抛出来,才有可能被处理,否则只会偷偷隐藏起来,寻觅时机给你致命一击。 + + +### 主动调用 + +在某些特殊场景中,开发者想要主动抛出一个异常,例如开头提到的在系统启动阶段读取文件失败。 + +对此,Rust 为我们提供了 `panic!` 宏,当调用执行该宏时,**程序会打印出一个错误信息,展开报错点往前的函数调用堆栈,最后退出程序**。 + +切记,一定是不可恢复的错误,才调用 `panic!` 处理,你总不想系统仅仅因为用户随便传入一个非法参数就崩溃吧?所以,**只有当你不知道该如何处理时,再去调用 panic!**. 首先,来调用一下 `panic!`,这里使用了最简单的代码实现,实际上你在程序的任何地方都可以这样调用: