context.WithCancel用于优雅终止goroutine,调用cancel()后ctx.Done()关闭,所有监听该信号的任务退出。

在Go语言中,context.WithCancel 是控制并发任务生命周期的重要工具。当你启动多个goroutine并希望在某个条件满足或发生错误时主动取消它们,使用
WithCancel可以优雅地通知所有相关任务终止执行。
创建可取消的Context
调用
context.WithCancel()会返回一个派生的 context 和一个 cancel 函数。调用该函数即可触发取消信号,所有监听这个 context 的 goroutine 都能收到通知。 示例代码:
ctx, cancel := context.WithCancel(context.Background()) defer cancel() // 确保在函数退出时释放资源
这里的
cancel是一个函数,用于显式关闭 context。一旦被调用,
ctx.Done()通道就会关闭,监听它的任务可以据此退出。
在Goroutine中监听取消信号
每个并发任务应定期检查 context 是否已被取消。通常通过 select 监听
ctx.Done()实现。
立即学习“go语言免费学习笔记(深入)”;
由于微信的大热,为了更好的方便使用微信的用户查询一些信息,这篇文章是入门级的微信公众平台开发教程,需要的朋友可以参考下 这篇入门教程将引导你完成如下任务: 创建百度云平台应用启用微信公众平台开发模式获取订阅、文字、图片、语音、视频消息回复文本、图文及音乐消息程序开发
for i := 0; i < 3; i++ {
go func(id int) {
for {
select {
case <-ctx.Done():
fmt.Printf("worker %d 收到取消信号\n", id)
return
default:
fmt.Printf("worker %d 正在工作...\n", id)
time.Sleep(500 * time.Millisecond)
}
}
}(i)
}
每个 worker 在每次循环中检查 context 状态。如果取消发生,立即退出,避免浪费资源。
主动触发取消
你可以在任意时刻调用
cancel()来停止所有关联的任务。这常用于超时、错误处理或用户中断场景。 例如,在主逻辑中等待一段时间后取消:
time.Sleep(2 * time.Second) cancel() // 触发取消,所有worker将退出
此时,所有正在运行的 worker 都会从
select中接收到
ctx.Done()的信号,并执行清理后退出。
注意事项与最佳实践
- 总是调用 defer cancel():防止 context 泄漏,确保系统资源及时释放。
- 不要传递 cancel 函数本身:context 应作为只读参数传递,cancel 函数由父级控制。
-
配合其他 context 方法使用:如
context.WithTimeout
或context.WithDeadline
,可更灵活地管理任务生命周期。 -
非阻塞检查取消:在 CPU 密集型循环中,定期轮询
ctx.Err()
或使用 select 避免长时间无法响应取消。
基本上就这些。合理使用
context.WithCancel能让并发程序更可控、更安全。关键是让每个任务尊重 context 的状态,及时退出。不复杂但容易忽略细节。









