• 如果A发生panic,B会挂掉!(程序整体会panic)
  • A协程的panic,只有A可以recover
func main() {
	go func() {
		for {
			fmt.Println("goroutine A is ok")
			time.Sleep(500 * time.Millisecond)
		}
	}()

	go func() {
		time.Sleep(1200 * time.Millisecond)
		panic("goroutine B panic")
	}()
	time.Sleep(time.Second * 3)
}
goroutine A is ok
goroutine A is ok
goroutine A is ok
panic: goroutine B panic

goroutine 7 [running]:
main.main.func2()
        /Users/bytedance/go/src/myself/test/main.go:18 +0x46
created by main.main
        /Users/bytedance/go/src/myself/test/main.go:16 +0x4d

Process finished with the exit code 2

所以开启协程,要记得协程自己recover

func main() {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				// 处理error
				fmt.Println(err)
			}
		}()
		//业务逻辑,如果发生panic,也会捕获
		panic("panic in the goroutine")
	}()
	//其它协程
	time.Sleep(time.Second)
}

结合上一篇errgroup,也要记得recover

func main() {
	var eg errgroup.Group
	for i := 0; i < 10; i++ {
		i := i //这里要有局部变量,不然eg.Go()里面的i都是同一个数
		eg.Go(func() error {
			defer func() { //开协程先用defer来recover
				if err := recover(); err != nil {
					fmt.Println(err)
				}
			}()
			time.Sleep(time.Second)
			if i > 6 {
				fmt.Println("error: ", i)
				return fmt.Errorf("error: i = %d", i)
			}
			if i == 6 {
				panic("panic at goroutine 6")
			}
			fmt.Println(i)
			return nil
		})
	}
	if err := eg.Wait(); err != nil { //err是errgroup遇到第一个error
		log.Fatal(err)
	}
}