1. 通过context来控制全体退出
在主协程中创建一个父context,之后的子协程都使用父context生成子context并传递过去
- context.WithCancelCause(contextFather)
生成子context
是一个channel,如果该context或者是父级的context执行了cancel(也可以理解为死掉了),那就会在这个channel中接收到东西,然后可以用于判断context是否退出了
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 26 27 28 29 30 31 32 33 34 35 36 37
| func main() { contextChild, _ := context.WithCancelCause(contextFather) go heart(contextChild, cancelFather) go func1(contextChild, cancelFather) select { case <-contextFather.Done(): time.Sleep(3 * time.Second) return } }
func heart(ctx context.Context, cancel context.CancelCauseFunc) { for { select { case <-ctx.Done(): return default: (具体心跳逻辑) } } }
func func1(ctx context.Context, cancel context.CancelCauseFunc) { for { select { case <-ctx.Done(): return default: (具体任务内容) } } }
|
2. 通过channel并发输出resp
- 通过参数传递同一个channel变量,实现多协程使用同一channel
- 进阶上面的context控制并发,再创一个输出resp任务
1 2 3 4 5 6 7 8 9 10 11
| func writeMessage(ctx context.Context, cancel context.CancelCauseFunc, resp chan []byte) { for { select { case <-ctx.Done(): return case data := <-resp: (具体输出逻辑) } } }
|