Can coroutine B catch panic of coroutine A

No, coroutines need to catch their own panic internally, other coroutines cannot catch

func main(a) {
   go func(a) { / / goroutine coroutines
      defer func(a) {
         if e := recover(a); e ! =nil { // Panic 111111 to catch the coroutine
            fmt.Println("recover ",e)
         }
      }()
      panic("0000000")
      fmt.Println("11111111") // Unable to print, panic terminates and does not execute subsequent logic} ()defer func(a) {
      if e := recover(a); e ! =nil { // Catch panic 222222 for the main coroutine
         fmt.Println("recover ",e)
      }
   }()
   panic("222222") // mian coroutine panic
   fmt.Println("33333") // Panic terminates and does not execute subsequent logic
   time.Sleep(2*time.Second) // Make sure the gofunc coroutine runs
}
Copy the code

Can RECOVER catch panic multiple times within a coroutine

No. An RECOVER can be captured only once

func main(a) {
   go func(a) { / / goroutine coroutines
      defer func(a) {
         if e := recover(a); e ! =nil { // Panic 111111 to catch the coroutine
            fmt.Println("recover ",e)
         }
      }()
      panic("0000000")
      panic("44444444") // The panic cannot be caught
      fmt.Println("11111111") // Unable to print, panic terminates and does not execute subsequent logic(1)}}Copy the code

How to use coroutine,recover,panic reasonably

You can encapsulate the logic using coroutines into functions in a project and manage entry processing uniformly

func callGoroutine(handlers ...func(a) error) (err error) {
   var wg sync.WaitGroup
   for _, f := range handlers {
      wg.Add(1)
      // Each function starts one coroutine
      go func(handler func(a) error) {
         defer func(a) {
            // Recover is used internally within each coroutine to catch panic that may occur in the calling logic
            if e := recover(a); e ! =nil {
               // Log failure information, catch panic, does not affect other coroutines running with the main coroutine
               fmt.Println("recover ",e)
            }
            defer wg.Done()
         }()
         // Take the first error handler to call the logic, and eventually return outward
         e := handler()
         if err == nil&& e ! =nil {
            err = e
         }
      }(f)
   }

   wg.Wait()

   return
}

func main(a) {
   userRpc := func(a) error {
      panic("userRpc fail ")
      return nil
   }

   // Invoke logic 2
   orderRpc := func(a) error {
      panic("orderRpc fail")
      return nil
   }

   err := callGoroutine(userRpc,orderRpc)
   iferr ! =nil {
      fmt.Println(err)
   }
}
Copy the code