Panic:处理不可恢复的错误
有时,会发生一些不好的事情,而你对此无能为力。在这些情况下,X 语言有 panic 宏。当 panic 宏执行时,你的程序会打印一条错误消息,展开并清理堆栈,然后退出。这种情况最常发生在检测到某种类型的 bug 并且程序员不清楚如何处理该错误时。
简单的 panic!
让我们看一个简单的程序,它调用 panic:
function main() {
panic("crash and burn")
}
当你运行这个程序时,你会看到类似这样的内容:
panic: crash and burn
该程序将立即退出,并显示给定的消息。
什么时候应该 panic?
决定何时应该 panic 以及何时应该返回 Result 可能很困难。让我们讨论一些可以帮助你做出决定的指导原则。
示例、原型设计和测试
在示例代码中,使用 panic(通常通过 unwrap 或 expect)通常是可以接受的。示例应该清晰易读,而 unwrap 和 expect 有助于实现这一点。
在原型设计时,在你决定如何处理错误情况之前,unwrap 和 expect 也是方便的占位符。它们明确标记了你稍后想要返回并实现正确错误处理的位置。
在测试中,如果测试失败,panic 是可以接受的——事实上,这正是测试检查预期行为的方式。
你比编译器知道得更多
在某些情况下,你可以确定 Result 将是 Ok,即使一般情况下不能保证。在这些情况下,使用 unwrap 或 expect 是可以接受的。这是一个例子:
let home: IpAddr = "127.0.0.1".parse().unwrap()
我们正在解析一个硬编码的字符串 "127.0.0.1",我们知道它是一个有效的 IP 地址。因此,在这里使用 unwrap 是可以接受的。但是,如果字符串来自用户输入,你应该正确处理 Result 而不是使用 unwrap。
不可恢复的错误
panic 的主要用例是当你遇到不可恢复的错误时——即程序无法继续执行的错误。这可能是由于:
- 代码中的 bug(例如,数组索引越界)
- 外部系统出现严重问题(例如,磁盘已满且无法写入)
- 违反了你的代码所依赖的不变量(例如,某人向你的函数传递了无效输入)
在这些情况下,继续执行可能比停止更糟糕,因此 panic 是合适的。
可恢复错误与不可恢复错误的指导原则
那么,你如何决定是返回 Result 还是 panic?这里有一些指导原则:
-
预计在正常情况下可能会失败的操作应该返回
Result。- 解析用户输入
- 连接到网络
- 打开可能不存在的文件
-
永远不应该失败的操作可以
panic。- 访问硬编码的有效索引处的数组元素
- 解析你知道有效的字符串
- 违反内部不变量
-
在原型设计中,你可以使用
unwrap或expect作为临时措施。 -
在示例代码中,
panic或unwrap/expect通常是可以接受的,因为它们使示例更清晰。
总结
panic宏停止程序执行并显示错误消息。- 在示例、原型设计和测试中使用
panic(通常通过unwrap或expect)通常是可以接受的。 - 对于你比编译器知道得更多并且可以保证
Result是Ok的情况,unwrap和expect也很有用。 - 对于预计在正常情况下可能会失败的操作,返回
Result而不是panic。 - 对于不可恢复的错误,使用
panic。
在本章中,我们介绍了 panic,它用于处理不可恢复的错误。结合上一章关于 Option 和 Result 的内容,你现在拥有了在 X 语言中处理各种错误情况所需的工具!
接下来,让我们学习泛型和 trait,它们允许你定义适用于多种类型的代码。