Go 中的恐慌恢复与其他语言中的 try catch
我刚刚阅读了关于恐慌/恢复的这篇文章在 Go 中,我不清楚这与其他主流语言中的 try/catch 有何不同。
I've just read this post about Panic/Recover in Go and I'm not clear on how this differs from try/catch in other mainstream languages.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
恐慌/恢复是函数范围内的。这就像说每个函数中只允许有一个 try/catch 块,并且 try 必须覆盖整个函数。这使得使用 Panic/Recover 变得非常烦人,就像 java/python/c# 等使用异常一样。这是故意的。
这也鼓励人们按照设计的方式使用 Panic/Recover。您应该从恐慌()中恢复(),然后将错误值返回给调用者。
Panic/Recover are function scoped. It's like saying that you're only allowed one try/catch block in each function and the try has to cover the whole function. This makes it really annoying to use Panic/Recover in the same way that java/python/c# etc. use exceptions. This is intentional.
This also encourages people to use Panic/Recover in the way that it was designed to be used. You're supposed to recover() from a panic() and then return an error value to the caller.
我一直在研究这个问题,试图想出最好的答案。最简单的方法是指出 panic/recover 的惯用用法,而不是 try/catch &|其他语言中的异常,或者这些习语背后的概念(基本上可以概括为“异常只应该发生在真正的异常情况下”)
但是它们之间的实际区别是什么?我会尽力总结。
与 try/catch 块相比的主要区别之一是控制流的方式。在典型的 try/catch 场景中,catch 块后面的代码将运行,除非它传播错误。 恐慌/恢复情况并非如此。恐慌会中止当前函数并开始展开堆栈,在遇到延迟函数时运行它们(恢复执行任何操作的唯一地方)。
实际上,我会更进一步:panic/recover几乎与try/catch完全不同,因为try和catch是(或至少表现得像)控制结构,而恐慌/恢复则不然。
这实际上源于这样一个事实:recover 是围绕 defer 机制构建的,(据我所知)这是 Go 中一个相当独特的概念。
当然还有更多,如果我能更好地表达我的想法,我会添加这些内容。
I keep looking at this question trying to think of the best way to answer it. It's easiest to just point to the idiomatic uses for panic/recover as opposed to try/catch &| exceptions in other languages, or the concepts behind those idioms (which can be basically summed up as "exceptions should only occur in truly exceptional circumstances")
But as to what the actual difference is between them? I'll try to summarize as best I can.
One of the main differences compared to try/catch blocks is the way control flows. In a typical try/catch scenario, the code after the catch block will run unless it propagates the error. This is not so with panic/recover. A panic aborts the current function and begins to unwind the stack, running deferred functions (the only place recover does anything) as it encounters them.
Really I'd take that even further: panic/recover is almost nothing like try/catch in the sense that try and catch are (or at least act like) control structures, and panic/recover are not.
This really stems out of the fact that recover is built around the defer mechanism, which (as far as I can tell) is a fairly unique concept in Go.
There are certainly more, which I'll add if I can actuate my thoughts a bit better.
我想我们都同意
panic
是throw
,recover
是catch
和defer
> 是终于
。最大的区别似乎是
recover
位于defer
内部。回到传统术语,它可以让您准确地决定在最后
的哪个时刻您想要捕获
任何东西,或者根本不捕获任何东西。I think we all agree that
panic
isthrow
,recover
iscatch
, anddefer
isfinally
.The big difference seems that
recover
goes insidedefer
. Going back to traditional terms, it lets you decide exactly at which point of yourfinally
you want to bothercatch
ing anything, or not at all.defer 不仅是一种处理错误的机制,而且还可以进行舒适且受控的清理。现在panic的作用就像其他语言中的raise()一样。在函数recover()的帮助下,您有机会在调用堆栈上升时捕获这种恐慌。这种方式几乎类似于try/catch。但是,后者适用于块恐慌/恢复适用于功能级别。
Rob Pike 关于此解决方案的原因:“我们不想鼓励将 Java 等语言中发生的错误和异常混为一谈。”。与其出现大量不同的异常和更多的用法,不如尽一切努力避免运行时错误,在确定后提供正确的错误返回值,并仅在没有其他方法时才使用恐慌/恢复。
defer is a mechanism not only for handling errors but also for doing a comfortable and controlled cleanup. Now panic works like raise() in other languages. With the help of the function recover() you've got the chance to catch this panic while it goes up the call stack. This way it's almost similar to try/catch. But while the latter works on blocks panic/recover works on function level.
Rob Pike about the reason for this solution: "We don't want to encourage the conflation of errors and exceptions that occur in languages such as Java.". Instead of having a large number of different exceptions with an even larger number of usages one should do everything to avoid runtime errors, deliver proper error return values after determination and use panic/recover only if there's no other way.
我认为 Panic 与 throw 相同,Recover 与 catch 相同。区别在于延迟。一开始我觉得defer和finally是一样的,后来发现defer比finally更灵活。 defer 可以放在函数的任何范围内,并记住当时参数的值,也可以更改返回的返回值,panic 可以出现在 defer 之后的任何位置。但由于缺少 try 块,除非整个函数返回,否则我们无法处理“异常”。我不认为这是一个缺点,也许GO想让你的方法只做一件事,任何异常都应该让这件事不能继续下去。
由于恐慌必须在延迟之后,它使得您必须在使用它之前处理它的“异常”。
这只是对我自己的了解。
I think the Panic is the same as throw,Recover is the same as catch. The difference is at defer. At the begin, I think defer is the same as finally,but later, I find defer is more flexible than finally. defer can be place at any scope of your function and remember the value of parameter at that moment and also can change the returned return value,the the panic can be at any where after defer. but because the missing of block of try, we can't process the "exception" unless the whole function returned. I don't think this is a disadvantage,maybe GO want to make your method only do one thing, any exception should make this thing can't go on.
and since panic must after defer, it make you must process its "exception" before use it.
this is just understanding of myself .
“go”与其他语言不同,它是一种并发语言,这意味着程序的各个部分并行运行。这意味着,如果设计者想要拥有与 catch/throw 类似的机制,则必须在此上下文中精心重新定义该机制。这解释了两种机制之间的差异。
"go" is unlike other languages a concurrent language, meaning that parts of the program runs in parallel. This means that if the designers want to have a similar mechanism as catch/throw , the mechanism has to meticulously redefined in this context. That explains the differences between the two mechanisms.
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这个超级工厂,所以还是有很多人在使用它。一门好的语言不在于它有的地方有多狗屎,而在于它是否有别人没有的亮点。
Panic/Recover is a compromised and simplified version of try/catch. What Panic/Recover can do, try/catch can do, and what try/catch can do, Panic/Recover may have to add a little extra code to accomplish. The reason why go doesn't use try/catch, but invented Panic/Recover, I think that no matter what reason the creator of go said, in fact, it's that try/catch/finally implementation is far more complex than Panic/Recover/defer, go creator doesn't want to run into this trouble, so can only throw the problem to the users. The good thing is that go on the one hand brought quite revolutionary goroutine, on the one hand, relying on the super factory google, so there are still a lot of people to use it. A good language is not about how shit it is in some places, but whether it has a bright spot that others do not have.