协程A的panic,协程B能捕获吗
不能,协程需要自己在内部捕获自己的panic,其他协程无法捕获
func main() {
go func() { // goroutine协程
defer func() {
if e := recover();e != nil { // 捕获该协程的panic 111111
fmt.Println("recover ",e)
}
}()
panic("0000000")
fmt.Println("11111111") // 无法打印,panic之后就终止了不再执行后续的逻辑
}()
defer func() {
if e := recover();e != nil { // 捕获main协程的panic 222222
fmt.Println("recover ",e)
}
}()
panic("222222 ") // mian 协程的panic
fmt.Println("33333") // panic之后就终止了不再执行后续的逻辑
time.Sleep(2*time.Second) // 保证运行gofunc协程
}
为什么不能捕获:
因为panic和recover是在G结构里边的,自然无法捕获其他协程的panic
一个协程内的recover能捕获多次panic吗
不能,一个recover只能捕获一次panic,一一对应
func main() {
go func() { // goroutine协程
defer func() {
if e := recover();e != nil { // 捕获该协程的panic 111111
fmt.Println("recover ",e)
}
}()
panic("0000000")
panic("44444444") // 该panic无法捕获
fmt.Println("11111111") // 无法打印,panic之后就终止了不再执行后续的逻辑
}()
}
如何合理的使用协程,recover ,panic
可以在项目中把使用协程的逻辑封装成函数,统一管理入口处理
func callGoroutine(handlers ...func() error) (err error) {
var wg sync.WaitGroup
for _, f := range handlers {
wg.Add(1)
// 每个函数启动一个协程
go func(handler func() error) {
defer func() {
// 每个协程内部使用recover捕获可能在调用逻辑中发生的panic
if e := recover(); e != nil {
// 日志记录失败信息,捕获panic,不影响其他协程跟主协程运行
fmt.Println("recover ",e)
}
defer wg.Done()
}()
// 取第一个报错的handler调用逻辑,并最终向外返回
e := handler()
if err == nil && e != nil {
err = e
}
}(f)
}
wg.Wait()
return
}
func main() {
userRpc := func() error {
panic("userRpc fail ")
return nil
}
// 调用逻辑2
orderRpc := func() error {
panic("orderRpc fail")
return nil
}
err := callGoroutine(userRpc,orderRpc)
if err != nil {
fmt.Println(err)
}
}