解决Golang父协程退出子协程不退出

情况如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fmt.Println("main函数开始...")
go func() {
fmt.Println("父协程开始...")
go func() {
for {
fmt.Println("子协程执行中...")
timer := time.NewTimer(time.Second * 2)
<-timer.C
}
}()
time.Sleep(time.Second*5)
fmt.Println("父协程退出...")
}()
time.Sleep(time.Second*10)
fmt.Println("main函数退出")

打印结果

1
2
3
4
5
6
7
8
9
main函数开始...
父协程开始...
子协程执行中...
子协程执行中...
子协程执行中...
父协程退出...
子协程执行中...
子协程执行中...
main函数退出

解决方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fmt.Println("main 函数开始...")
go func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fmt.Println("父协程开始...")
go func(ctx context.Context) {
for {
for {
select {
case <-ctx.Done():
fmt.Println("子协程接受停止信号...")
return
default:
fmt.Println("子协程执行中...")
timer := time.NewTimer(time.Second * 2)
<-timer.C
}
}
}
}(ctx)
time.Sleep(time.Second*5)
fmt.Println("父协程退出...")
}()
time.Sleep(time.Second*10)
fmt.Println("main函数退出")

执行结果如下:

1
2
3
4
5
6
7
8
main函数开始...
父协程开始...
子协程执行中...
子协程执行中...
子协程执行中...
父协程退出...
子协程接受停止信号...
main 函数 退出

结论

上述执行后发现,控制台打印了err和父亲协程退出,但是程序依旧在打印子协程。由此得知协程无父子关系,即在父协程开启新的协程,若父协程退出,不影响子协程。