主线程中启动A协程,A协程中启动B协程,B协程中启动C协程,现A协程出现Panic,B和C正常。
context解决方式func A(ctx context.Context) { ctx, cancel := context.WithCancel(ctx) defer func() { if err := recover(); err != nil { log.Println("recover from panic:", err) cancel() } }() log.Println("A") go B(ctx) time.Sleep(10 * time.Second) panic("err") } func B(ctx context.Context) { go C(ctx) // task for { select { case <-ctx.Done(): log.Printf("b quit ctx.Done(): %v n", ctx.Err()) return default: } log.Println("b") time.Sleep(1 * time.Second) } } func C(ctx context.Context) { for { select { case <-ctx.Done(): log.Printf("c quit ctx.Done(): %v n", ctx.Err()) return default: } log.Println("c") time.Sleep(1 * time.Second) } }channel解决方式
func A() { signalCh := make(chan struct{}) wg := sync.WaitGroup{} defer func() { if err := recover(); err != nil { log.Println(err) close(signalCh) wg.Wait() } }() go B(&wg, signalCh) time.Sleep(2 * time.Second) panic("A") } func B(wg *sync.WaitGroup, ch <-chan struct{}) { wg.Add(1) defer func() { wg.Done() }() log.Println("B start") go C(wg, ch) for { select { case <-ch: log.Println("exit B") return default: } log.Println("B") time.Sleep(time.Second) } } func C(wg *sync.WaitGroup, ch <-chan struct{}) { wg.Add(1) defer func() { wg.Done() }() log.Println("C start") for { select { case <-ch: log.Println("exit C") return default: } log.Println("C") time.Sleep(time.Second) } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)