我理解使用处理恐慌恢复。但是,当在例行程序中出现恐慌时,以下块无法恢复
func main() {
done := make(chan int64)
defer fmt.Println("Graceful End of program")
defer func() {
r := recover()
if _, ok := r.(error); ok {
fmt.Println("Recovered")
}
}()
go handle(done)
for {
select{
case <- done:
return
}
}
}
func handle(done chan int64) {
var a *int64
a = nil
fmt.Println(*a)
done <- *a
}
但是下面的块能够按预期执行
func main() {
done := make(chan int64)
defer fmt.Println("Graceful End of program")
defer func() {
r := recover()
if _, ok := r.(error); ok {
fmt.Println("Recovered")
}
}()
handle(done)
for {
select{
case <- done:
return
}
}
}
func handle(done chan int64) {
var a *int64
a = nil
fmt.Println(*a)
done <- *a
}
如何从日常生活中出现的恐慌中恢复过来。以下是操场的链接:https://play.golang.org/p/lkvKUxMHjhi
答案 0 :(得分:6)
恢复仅在调用恐慌时从同一goroutine调用时有效。来自golang博客:
进程继续向上移动,直到当前所有函数 goroutine已经返回,此时程序崩溃
你必须在goroutine中进行延迟恢复。
https://blog.golang.org/defer-panic-and-recover
docs / spec也包括相同的内容:
执行函数F时,显式调用panic或运行时 panic终止F的执行。任何由F推迟的函数都是 然后像往常一样执行。接下来,任何延迟函数由F的调用者运行 运行,依此类推,直至由顶级函数推迟 执行goroutine 。那时,程序终止了 报告错误条件,包括参数的值 恐慌。此终止序列称为恐慌
答案 1 :(得分:0)
我使用以下方式来处理这种情况,它按预期工作。
package main
import (
"fmt"
"time"
)
func main() {
defer fmt.Println("Graceful End of program")
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()
done := make(chan int64)
var panicVar interface{}
go handle(done, &panicVar)
WAIT:
for {
select {
case <-done:
break WAIT // break WAIT: goroutine exit normally
default:
if panicVar != nil {
break WAIT // break WAIT: goroutine exit panicked
}
// wait for goroutine exit
}
time.Sleep(1 * time.Microsecond)
}
if panicVar != nil {
panic(panicVar) // panic again
}
}
func handle(done chan int64, panicVar *interface{}) {
defer func() {
if r := recover(); r != nil {
// pass panic variable outside
*panicVar = r
}
}()
var a *int64
a = nil
fmt.Println(*a)
done <- *a
}