英文:
panic and recover from a package
问题
我正在尝试弄清楚panic()
和recover()
的工作原理。
#log包
package log
import (
"fmt"
)
func Recover() {
fmt.Println("正在恢复!")
if err := recover(); err != nil {
fmt.Println("错误消息已恢复!")
}
}
#main包
package main
import (
"fmt"
log "www/pkg/log"
)
func main() {
defer func() {
log.Recover()
}()
panic("假错误!")
}
#输出
正在恢复!
panic: 假错误!
为什么错误消息已恢复!
从未打印出来?
英文:
I'm trying to figure out how panic()
and recover()
works..
#log package
package log
import (
"fmt"
)
func Recover() {
fmt.Println("Recovering!")
if err := recover(); err != nil {
fmt.Println("Error message recovered!")
}
}
#main package
package main
import (
"fmt"
log "www/pkg/log"
)
func main() {
defer func() {
log.Recover()
}()
panic("Fake error!")
}
#output
Recovering!
panic: Fake error!
Why is Error message recovered!
never printed?
答案1
得分: 2
应用程序必须直接从延迟函数中调用recover来处理panic。
规范中提到了延迟函数调用recover的情况:
假设函数G延迟调用了函数D,而函数D又调用了recover,并且在执行G的goroutine中的某个函数中发生了panic。当延迟函数的运行达到D时,D调用recover的返回值将是panic调用时传递的值。
这是一个微妙的问题,它不允许对recover进行间接调用。此外,关于recover的返回值的部分提到了从延迟函数中直接调用:
如果满足以下任一条件,则recover的返回值为nil:
- recover不是由延迟函数直接调用的。
最近我遇到了这个问题。由于规范非常简洁,有时需要仔细阅读才能理解其中的一些要点。
英文:
The application must call recover directly from the deferred function to handle the panic.
The specification talks about the deferred function calling recover:
> Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing. When the running of deferred functions reaches D, the return value of D's call to recover will be the value passed to the call of panic.
It's subtle, but it does not allow for an indirect call to recover. Also, the passage on the return value from recover mentions a direct call from the deferred function:
> The return value of recover is nil if any of the following conditions holds:
>
> - recover was not called directly by a deferred function.
I was caught by this issue recently. Because the specification is very concise, it sometimes takes careful reading to pick up some points.
答案2
得分: 1
recover
只针对当前的goroutine执行:文档中说:
在延迟函数中执行recover的调用(但不包括由其调用的任何函数)会通过恢复正常执行来停止panic序列
当你调用另一个函数时,它没有发生panic,因此在其中间调用recover会返回nil,你无法捕获到panic。
英文:
revocer
only refers to the execution of the current goroutine: The docs say:
Executing a call to recover inside a deferred function **(but not any function called by it)** stops the panicking sequence by restoring normal execution
When you called another function, it did not panic, hence calling recover in the middle of it returns nil, and you do not catch the panic.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论