Go vs. 中的恐慌恢复try catch 用其他语言
Posted
技术标签:
【中文标题】Go vs. 中的恐慌恢复try catch 用其他语言【英文标题】:Panic recover in Go v.s. try catch in other languages 【发布时间】:2011-03-25 17:04:52 【问题描述】:我刚刚阅读了this post 关于 Go 中的 Panic/Recover 的内容,但我不清楚这与其他主流语言中的 try/catch 有何不同。
【问题讨论】:
【参考方案1】:我一直在研究这个问题,试图找出最好的答案。最简单的方法是指出 panic/recover 的惯用用法,而不是 try/catch &|其他语言中的异常,或者这些习语背后的概念(基本上可以概括为“异常只应在真正例外的情况下发生”)
但至于它们之间的实际区别是什么?我会尽量总结一下。
与 try/catch 块相比的主要区别之一是控制流的方式。在典型的 try/catch 场景中,catch 块之后的代码将运行,除非它传播错误。 恐慌/恢复并非如此。恐慌中止当前函数并开始展开堆栈,在遇到延迟函数时运行延迟函数(recover 唯一可以做任何事情的地方)。
真的,我会更进一步:panic/recover 几乎不像 try/catch,因为 try 和 catch 是(或至少表现得像) 控制结构,而 panic/recover 不是。
这实际上源于恢复是围绕延迟机制构建的,这(据我所知)在 Go 中是一个相当独特的概念。
当然还有更多,如果我能更好地驱动我的想法,我会添加。
【讨论】:
谢谢,顺便说一句,defer
与 D 的 scope
非常相似
这是我的看法:恐慌大致类似于投掷。带有recover 语句的defer 大致类似于catch。与 try 块最接近的模拟是当前函数的主体。
那么从使用角度来看有什么区别呢?现在在我看来,它的行为就像一个 try/catch 块,限制跨越整个函数(即你不能有多个这样的块)并且恢复是一种获取类似异常的对象的方法。并且限制异常不会超出您的范围。
这篇文章非常教条。 “恐慌中止当前函数并开始展开堆栈”也是异常的作用。 Panic/recover 和 throw/catch 在语义上是同一问题的不同解决方案
@Espen 十年后,我确信我会做出不同的解释(希望更好),但该声明的上下文是在恐慌/恢复与抛出/捕获的上下文中,而不仅仅是恐慌与投掷。是的,panic 和 throw 都开始展开堆栈,但是在 go 中无法恢复当前函数的执行,而 catch 确实允许您恢复当前函数。【参考方案2】:
我想我们都同意panic
是throw
,recover
是catch
,defer
是finally
。
最大的区别似乎是recover
进入了defer
。回到传统术语,它可以让您准确地决定在您的 finally
的哪一点上您想打扰 catch
任何事情,或者根本不打扰。
【讨论】:
【参考方案3】:我认为 Panic 与 throw 相同,Recover 与 catch 相同。区别在于延迟。一开始觉得defer和finally是一样的,后来发现defer比finally灵活多了。 defer 可以放在函数的任何范围内,并记住当时参数的值,也可以更改返回的返回值,恐慌可以在 defer 之后的任何地方。但是由于缺少try块,除非整个函数返回,否则我们无法处理“异常”。我不认为这是一个缺点,也许 GO 想让你的方法只做一件事,任何异常都应该让这件事不能继续下去。 而且由于 panic 必须在 defer 之后,它使你必须在使用它之前处理它的“异常”。
这只是对我自己的理解。
【讨论】:
【参考方案4】:恐慌/恢复是功能范围的。这就像说每个函数中只允许一个 try/catch 块,并且 try 必须覆盖整个函数。这使得以与 java/python/c# 等使用异常相同的方式使用 Panic/Recover 非常烦人。这是故意的。 这也鼓励人们以设计使用的方式使用 Panic/Recover。你应该从 panic() 中恢复(),然后返回一个错误值给调用者。
【讨论】:
【参考方案5】:defer 是一种机制,不仅用于处理错误,还用于进行舒适且受控的清理。现在恐慌在其他语言中就像 raise() 一样工作。在函数 recover() 的帮助下,您有机会在它上升到调用堆栈时捕捉到这种恐慌。这种方式几乎类似于 try/catch。但是,虽然后者适用于块,但恐慌/恢复适用于功能级别。
Rob Pike 关于此解决方案的原因:“我们不想鼓励将 Java 等语言中出现的错误和异常混为一谈。”。与其有大量不同的异常和更多的用法,不如尽一切努力避免运行时错误,在确定后提供正确的错误返回值,并仅在没有其他方法时使用恐慌/恢复。
【讨论】:
以上是关于Go vs. 中的恐慌恢复try catch 用其他语言的主要内容,如果未能解决你的问题,请参考以下文章