2 回答
TA贡献1842条经验 获得超12个赞
一些历史:
在 Go 的早期(1.0 版之前),没有recover()
. 调用panic()
将终止应用程序而没有任何方法可以阻止它。
我找到了导致添加的原始讨论recover()
,您可以在 golang-nuts 讨论论坛上阅读它:
类似异常机制的提议
请注意:讨论可以追溯到 2010 年 3 月 25 日,而且相当冗长(150 个帖子,共 6 页)。
最终它是在2010-03-30添加的:
此版本包含三个语言更改:
用于报告和从故障中恢复的函数
panic
andrecover
已添加到规范中:
http : //golang.org/doc/go_spec.html#Handling_panics
在相关更改中,panicln
已消失,panic
现在是单参数函数. gc 编译器可以识别恐慌和恢复,但新行为尚未实现。
多返回值和约定提供了一种更清晰的方式来处理 Go 中的错误。
然而,这并不意味着在某些(罕见的)情况下,恐慌恢复没有用。
引用官方FAQ:为什么Go没有异常?
Go 还具有一些内置函数,用于发出信号并从真正的异常情况中恢复。恢复机制仅在发生错误后被拆除的函数状态的一部分执行,这足以处理灾难,但不需要额外的控制结构,如果使用得当,可以产生干净的错误处理代码。
这是一个关于何时/如何有用的“现实生活”示例:引自博客文章Defer, Panic and Recover:
有关panic和recovery的真实示例,请参阅Go 标准库中的json 包。它使用一组递归函数解码 JSON 编码的数据。当遇到异常JSON,解析器呼叫恐慌展开栈到顶层的函数调用,从恐慌并返回一个适当的错误值中恢复(见“错误”,并在decodeState类型的“解组”方法的解码.去)。
另一个例子是当您编写调用用户提供的函数的代码(例如包)时。您不能相信所提供的功能不会恐慌。一种方法是不处理它(让恐慌结束),或者您可以选择通过从这些恐慌中恢复来“保护”您的代码。一个很好的例子是标准库中提供的http 服务器:您提供服务器将调用的函数(处理程序或处理程序函数),如果您的处理程序发生恐慌,服务器将从这些恐慌中恢复并且不会让您的完整应用程序模具。
你应该如何使用它们:
Go 库中的约定是,即使包在内部使用 panic,其外部 API 仍会显示明确的错误返回值。
TA贡献1852条经验 获得超1个赞
我认为您的问题是您维护的一种心理模型的结果,该模型是由流行的主流语言(例如 Java、C++、C#、PHP 和无数其他语言)灌输的,这些语言只是错误地出现了异常。
问题是,异常本身并不是一个错误的概念,而是滥用它们来处理实际上并非异常的情况。我个人最讨厌的是 Java 的文件系统处理 API(和 .NET,它几乎逐字复制了 Java 的 API):如果该文件不存在,为什么无法打开文件会导致异常?文件系统是一种固有的 racy 媒体,并被指定为 racy,因此在打开文件进行读取之前确保文件存在的唯一正确方法是打开它然后检查“文件不存在”错误:不存在的文件一点也不例外。
因此,Go 清楚地将异常情况与普通的正常错误区分开来。Go 处理错误的立场的座右铭是“错误就是值”,因此正常的预期错误作为值处理,并panic()
用于处理异常情况。一个很好的简单例子:
尝试取消引用
nil
指针会导致panic
.基本原理:您的代码继续并尝试取消引用不指向任何值的指针。紧随其后的代码明确期望该值可用——作为解引用操作的结果。因此,控制流显然不能以任何合理的方式正常进行,这就是为什么这是一种例外情况:在正确的程序中,
nil
指针的解引用不会发生。TCP 流的远程端突然关闭了其一侧的流,下一次尝试读取它导致错误。
这是很正常的情况:人们不能理智地期望 TCP 会话是坚如磐石的:网络中断、数据包丢失、意外断电确实会发生,我们必须为远程对等方意外关闭流做好准备。
一个小小的转折panic()
是 Go 不会强迫你盲目地遵循某些教条,并且你可以在严格控制的特定情况下自由地“滥用”恐慌/恢复,例如panic
国王用错误值从深度嵌套的处理循环中跳出已知并在现场检查的特定类型recover
。
- 2 回答
- 0 关注
- 138 浏览
添加回答
举报