通知子 goroutine 退出的三种方式
1 全局变量
1 | package main |
- 定义全局变量 exit 用于表示是否要求子 goroutine 退出
- 父 goroutine 中设置全局变量 exit 的值
- 子 goroutine 中循环检测全局变量 exit 的值,如果为 true,则结束这个子 goroutine
2 Channel
1 | package main |
- 定义无缓冲的管道 exitChan 用于表示是否要求子 goroutine 退出
- select 多路复用,监听管道 exitChan 中是否有值。如果有值就结束子 goroutine;如果没有值,就执行默认操作
- 注意:如果没有default,select会阻塞在等待exitChan有值,因为这里定义的管道是无缓冲的
3 Context
3.1 context.WithCancel
3.1.1 开启1个子goroutine
1 | package main |
- context.WithCancel 函数返回父context的子context,和一个函数对象cancel用于通知子goroutine结束
- context内部维护了一个管道,context对象ctx调用Done方法,返回只读形式的管道
- 子goroutine中select多路复用,监听管道ctx.Done。如果有值,则结束子goroutine;否则,执行默认操作
- 调用 cancel 函数对象,通知子goroutine结束
3.1.2 开启多个子goroutine
1 | package main |
- 使用context可以很方便地处理通知多个子goroutine结束的情况
3.2 context.WithDeadline
1 | package main |
- 上面的代码,定义了一个50ms过期的deadline
- 调用context.WithDeadline函数,得到子上下文ctx,和一个取消函数cancel
- 子goroutine中select多路复用,监听管道ctx.Done。如果有值,则结束子goroutine;否则,执行默认操作
- 两种情况会向管道 ctx.Done 中发送结束信号:① 截止时间到,ctx对象自动向内部维护的管道发送结束信号 ② 手动调用 cancel 函数,通知子 goroutine 结束
3.3 context.WithTimeout
1 | package main |
- 调用context.WithTimeout函数,指定超时时间,得到子上下文ctx,和一个取消函数cancel
- 子goroutine中select多路复用,监听管道ctx.Done。如果有值,则结束子goroutine;否则,执行默认操作
- 两种情况会向管道 ctx.Done 中发送结束信号:① 超时时间到,ctx对象自动向内部维护的管道发送结束信号 ② 手动调用 cancel 函数,通知子 goroutine 结束