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

Panic:处理不可恢复的错误

有时,会发生一些不好的事情,而你对此无能为力。在这些情况下,X 语言有 panic 宏。当 panic 宏执行时,你的程序会打印一条错误消息,展开并清理堆栈,然后退出。这种情况最常发生在检测到某种类型的 bug 并且程序员不清楚如何处理该错误时。

简单的 panic!

让我们看一个简单的程序,它调用 panic

function main() {
  panic("crash and burn")
}

当你运行这个程序时,你会看到类似这样的内容:

panic: crash and burn

该程序将立即退出,并显示给定的消息。

什么时候应该 panic?

决定何时应该 panic 以及何时应该返回 Result 可能很困难。让我们讨论一些可以帮助你做出决定的指导原则。

示例、原型设计和测试

在示例代码中,使用 panic(通常通过 unwrapexpect)通常是可以接受的。示例应该清晰易读,而 unwrapexpect 有助于实现这一点。

在原型设计时,在你决定如何处理错误情况之前,unwrapexpect 也是方便的占位符。它们明确标记了你稍后想要返回并实现正确错误处理的位置。

在测试中,如果测试失败,panic 是可以接受的——事实上,这正是测试检查预期行为的方式。

你比编译器知道得更多

在某些情况下,你可以确定 Result 将是 Ok,即使一般情况下不能保证。在这些情况下,使用 unwrapexpect 是可以接受的。这是一个例子:

let home: IpAddr = "127.0.0.1".parse().unwrap()

我们正在解析一个硬编码的字符串 "127.0.0.1",我们知道它是一个有效的 IP 地址。因此,在这里使用 unwrap 是可以接受的。但是,如果字符串来自用户输入,你应该正确处理 Result 而不是使用 unwrap

不可恢复的错误

panic 的主要用例是当你遇到不可恢复的错误时——即程序无法继续执行的错误。这可能是由于:

  • 代码中的 bug(例如,数组索引越界)
  • 外部系统出现严重问题(例如,磁盘已满且无法写入)
  • 违反了你的代码所依赖的不变量(例如,某人向你的函数传递了无效输入)

在这些情况下,继续执行可能比停止更糟糕,因此 panic 是合适的。

可恢复错误与不可恢复错误的指导原则

那么,你如何决定是返回 Result 还是 panic?这里有一些指导原则:

  • 预计在正常情况下可能会失败的操作应该返回 Result

    • 解析用户输入
    • 连接到网络
    • 打开可能不存在的文件
  • 永远不应该失败的操作可以 panic

    • 访问硬编码的有效索引处的数组元素
    • 解析你知道有效的字符串
    • 违反内部不变量
  • 在原型设计中,你可以使用 unwrapexpect 作为临时措施。

  • 在示例代码中,panicunwrap/expect 通常是可以接受的,因为它们使示例更清晰。

总结

  • panic 宏停止程序执行并显示错误消息。
  • 在示例、原型设计和测试中使用 panic(通常通过 unwrapexpect)通常是可以接受的。
  • 对于你比编译器知道得更多并且可以保证 ResultOk 的情况,unwrapexpect 也很有用。
  • 对于预计在正常情况下可能会失败的操作,返回 Result 而不是 panic
  • 对于不可恢复的错误,使用 panic

在本章中,我们介绍了 panic,它用于处理不可恢复的错误。结合上一章关于 OptionResult 的内容,你现在拥有了在 X 语言中处理各种错误情况所需的工具!

接下来,让我们学习泛型和 trait,它们允许你定义适用于多种类型的代码。