除了错误处理之外,为什么Go会增加恐慌和恢复?

zla*_*ski 11 error-handling exception-handling go

为什么Go最终会采用恐慌/恢复的异常处理,当语言如此惯用并且是错误代码的强烈提倡者时?Go的设计者有哪些场景不会被错误代码处理并且需要恐慌/恢复?

我理解约定说限制恐慌/恢复,但运行时是否也限制它们不能用作C++中的常规throw/catch?

icz*_*cza 12

一些历史:

在Go的早期(版本1.0之前),没有recover().调用panic()将终止一个应用程序而无法阻止它.

我找到了导致添加的原始讨论recover(),你可以在golang-nuts讨论论坛上阅读:

关于类似异常机制的提案

请注意:讨论的历史可以追溯到2010年3月25日,这是非常令人精疲力尽的(150页至6页).

最终它被添加到2010-03-30:

此版本包含三种语言更改:

  1. 功能panicrecover,用于报告和从故障中恢复,已添加到规范:
    http://golang.org/doc/go_spec.html#Handling_panics
    在相关的变化,panicln时代已经过去了,panic现在是一个单参数函数.恐慌和恢复被gc编译器识别,但新行为尚未实现.

多返回值和约定提供了一种更简洁的方法来处理Go中的错误.

然而,这并不意味着在某些(罕见)情况下恐慌恢复无效.

引自官方常见问题解答:为什么Go没有例外?

Go还有一些内置功能,可以在真正特殊的条件下发出信号并从中恢复.恢复机制仅作为函数状态在错误发生后被拆除的一部分执行,这足以处理灾难但不需要额外的控制结构,并且如果使用得当,可以产生干净的错误处理代码.

以下是关于何时/如何有用的"现实生活"示例:引用博客文章Defer,Panic and Recover:

有关恐慌恢复的真实示例,请参阅Go标准库中的json包.它使用一组递归函数对JSON编码的数据进行解码.当遇到格式错误的JSON时,解析器调用panic将堆栈展开到顶级函数调用,该函数调用从恐慌中恢复并返回适当的错误值(请参阅解码中的decodeState类型的'error'和'unmarshal'方法).go).

另一个例子是当你编写调用用户提供的函数的代码(例如包)时.你不能相信它提供的功能,它不会恐慌.一种方法是不处理它(让恐慌结束),或者你可以选择通过从那些恐慌中恢复来"保护"你的代码.一个很好的例子是标准库中提供的http服务器:你是提供服务器将调用的函数(处理程序处理程序函数)的那个,如果你的处理程序恐慌,服务器将从那些恐慌中恢复而不是让你的完整申请模具.

你应该如何使用它们:

Go库中的约定是即使包在内部使用panic,其外部API仍然会显示明确的错误返回值.

相关和有用的读物​​:

http://blog.golang.org/defer-panic-and-recover

http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right

https://golang.org/doc/faq#exceptions

http://evanfarrer.blogspot.co.uk/2012/05/go-programming-language-has-exceptions.html

  • 感谢您挖掘历史,非常有见地 (3认同)
  • @zlatanski,不,对你所指的案件使用"恐慌"显然是*滥用*这个特征.但问题是,滥用它会使代码比检查标志等更易读/可理解和可维护.最好放弃一些纯度并且在可维护性方面胜过其他方式;-) (2认同)