我创建了一个示例,在其中并发运行函数,在函数中我触发了恐慌并进行了恢复:
package main
import "fmt"
func main() {
// "main" recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("main goroutine paniced:", r)
}
}()
// running function concurrently inside which I panic
chanStr := make(chan string)
go func() {
// this "internal" goroutin recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("internal goroutine paniced:", r)
}
chanStr <- "hello world"
}()
// panicking and wanting recovery not only in "internal" recovery but in "main" recovery as well
panic("NOT main goroutine")
}()
// waiting for chan with "internal" goroutine panicking and recovery
str := <-chanStr
fmt.Println(str)
// panic("main")
}
它会输出:
internal goroutine panicked: NOT main goroutine
hello world
我能否修改代码,将从“internal”恢复密码更改为“main”?换句话说,我想让它在控制台中写下:
internal goroutine paniced: NOT main goroutine
main goroutine paniced: main
hello world
我尝试通过完全删除“内部”恢复功能来实现这一点,但在这种情况下,“主”恢复无法恢复“内部” goroutine 中的 panic。 Playground
更新
我尝试遵循 @Momer 的建议,通过通道发送错误并在主 goroutine 中处理它,而不是尝试将 panic 冒泡:package main
import (
"errors"
"fmt"
)
func main() {
// "main" recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("main goroutine paniced:", r)
}
}()
// running func concarantly inside which I panic
chanStr := make(chan string)
chanErr := make(chan error)
var err error
go func() {
// this "internal" goroutin recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("internal goroutine paniced:", r)
switch t := r.(type) {
case string:
fmt.Println("err is string")
err = errors.New(t)
case error:
fmt.Println("err is error")
err = t
default:
fmt.Println("err is unknown")
err = errors.New("Unknown error")
}
chanErr <- err
chanStr <- ""
}
}()
// panicing and wanting recovery not only in "internal" recovery but in "main" recovery as well
panic("NOT main goroutine")
chanStr <- "hello world"
chanErr <- nil
}()
// waiting for chan with "internal" goroutin panicing and recovery
str := <-chanStr
err = <-chanErr
fmt.Println(str)
fmt.Println(err)
// panic("main")
}
它出现了错误
all goroutines are asleep - deadlock
完整输出:
go run /goPath/parentRecoverty2.go
internal goroutine paniced: NOT main goroutine
err is string
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/goPath/parentRecoverty2.go:48 +0x1d4
goroutine 5 [chan send]:
main.func·002()
/goPath/parentRecoverty2.go:37 +0x407
main.func·003()
/goPath/parentRecoverty2.go:42 +0x130
created by main.main
/goPath/parentRecoverty2.go:46 +0x190
exit status 2
all goroutines are asleep - deadlock
,请查看我上面的更新。 - Maxim YefremovchanErr
和chanStr
中写了一次:chanErr <- err chanStr <- ""
。 - Maxim Yefremov