Go vs. 中的恐慌恢复尝试使用其他语言来捕获

问题描述 投票:0回答:7

我刚刚阅读了关于 Go 中的 Panic/Recover 的这篇文章,我不清楚这与其他主流语言中的 try/catch 有何不同。

exception error-handling go
7个回答
31
投票

紧急/恢复是函数范围内的。这就像说每个函数中只允许有一个 try/catch 块,并且 try 必须覆盖整个函数。这使得使用 Panic/Recover 变得非常烦人,就像 java/python/c# 等使用异常一样。这是故意的。 这也鼓励人们按照设计的方式使用 Panic/Recover。您应该从恐慌()中恢复(),然后将错误值返回给调用者。


25
投票

我一直在看着这个问题,试图想出最好的答案。最简单的方法就是指出 panic/recover 的惯用用法,而不是 try/catch &|其他语言中的异常,或者这些习语背后的概念(基本上可以概括为“异常应该只发生在真正的异常情况下”)

但是至于它们之间的实际区别是什么?我会尽力总结。

try/catch 块相比的主要区别之一是控制流的方式。在典型的 try/catch 场景中,catch 块后面的代码将运行,除非它传播错误。 恐慌/恢复则不是这样。恐慌会中止当前函数并开始展开堆栈,在遇到延迟函数时运行它们(恢复执行任何操作的唯一地方)。

我真的会更进一步:panic/recover几乎与try/catch完全不同,因为try和catch是(或至少表现得像)控制结构,而panic/recover不是.

这确实源于这样一个事实:recover 是围绕 defer 机制构建的,据我所知,这是 Go 中一个相当独特的概念。

当然还有更多,如果我能更好地发挥我的想法,我会添加的。


19
投票

我想我们都同意

panic
throw
recover
catch
defer
finally

最大的区别似乎是

recover
进入了
defer
。回到传统的术语,它可以让你准确地决定在你的
finally
的哪个点上你想要打扰
catch
任何事情,或者根本不打扰。


10
投票

defer 不仅是一种处理错误的机制,而且还可以进行舒适且受控的清理。现在panic的作用就像其他语言中的raise()一样。在函数recover()的帮助下,您有机会在调用堆栈上升时捕获这种恐慌。这种方式几乎类似于try/catch。但是,虽然后者适用于块恐慌/恢复,但适用于功能级别。

Rob Pike 关于此解决方案的原因:“我们不想鼓励将 Java 等语言中发生的错误和异常混为一谈。”。与其拥有大量不同的异常和更多的使用次数,不如尽一切努力避免运行时错误,在确定后提供正确的错误返回值,并仅在没有其他方法时才使用恐慌/恢复。


4
投票

我认为 Panic 和 throw 一样,Recover 和 catch 一样。区别在于延迟。一开始我觉得defer和finally是一样的,后来发现defer比finally更灵活。 defer 可以放在函数的任何范围内,并记住当时参数的值,也可以更改返回的返回值,panic 可以出现在 defer 之后的任何位置。但由于缺少 try 块,除非整个函数返回,否则我们无法处理“异常”。我不认为这是一个缺点,也许GO想让你的方法只做一件事,任何异常都应该让这件事不能继续下去。 并且由于恐慌必须在延迟之后,它使得你必须在使用它之前处理它的“异常”。

这只是我自己的理解。


1
投票

“go”与其他语言不同,它是一种并发语言,这意味着程序的各个部分并行运行。这意味着,如果设计者想要拥有与 catch/throw 类似的机制,则必须在此上下文中精心重新定义该机制。这解释了两种机制之间的差异。


0
投票

Panic/Recover 是 try/catch 的妥协和简化版本。 Panic/Recover能做什么,try/catch能做什么,而try/catch能做什么,Panic/Recover可能还需要添加一点额外的代码才能完成。 go之所以不使用try/catch,而是发明了Panic/Recover,我想无论go的创造者说的是什么理由,其实都是try/catch/finally的实现远比Panic/Recover复杂/defer,go Creator 不想遇到这个麻烦,所以只能把问题抛给用户。好在Go一方面带来了相当革命性的goroutine,一方面依托于google这个超级工厂,所以还是有很多人在使用它。一门好的语言,不是看它有的地方有多狗屎,而是看它是否有别人没有的亮点。

© www.soinside.com 2019 - 2024. All rights reserved.