0

0

Golang使用context取消并发任务

P粉602998670

P粉602998670

发布时间:2026-01-07 12:56:43

|

991人浏览过

|

来源于php中文网

原创

context.WithCancel 是最直接的取消方式,返回可取消 Context 和 cancel 函数,调用后者立即关闭 ctx.Done();必须配对调用 cancel()(推荐 defer),且需检查 ctx.Err() 区分取消原因。

golang使用context取消并发任务

context.WithCancel 是最直接的取消方式

当需要手动触发取消时,context.WithCancel 是首选。它返回一个可取消的 Context 和一个 cancel 函数,调用后者会立即关闭 ctx.Done() 的 channel。

常见错误是忘记调用 cancel() —— 这会导致 goroutine 泄漏,尤其在循环或高频创建 context 的场景中。

  • 每次调用 context.WithCancel 都必须配对调用 cancel(),建议用 defer cancel()(除非明确需延迟取消)
  • 不要把 cancel 传给不可信的第三方函数,它可能被意外调用
  • ctx.Done() 关闭后,再次调用 cancel() 是安全的,但无实际效果
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 确保退出前清理

go func() { select { case <-time.After(2 * time.Second): fmt.Println("task done") case <-ctx.Done(): fmt.Println("task canceled:", ctx.Err()) // context.Canceled } }()

time.Sleep(1 * time.Second) cancel() // 主动触发取消

select + ctx.Done() 必须配合 error 检查

仅监听 ctx.Done() 不足以判断是否真因取消退出——还需检查 ctx.Err(),否则无法区分是超时、取消,还是父 context 被关闭。

典型误用:在 select 中只读 就直接返回,不校验 ctx.Err(),导致日志或错误处理逻辑错判原因。

立即学习go语言免费学习笔记(深入)”;

  • ctx.Err()ctx.Done() 关闭后才返回非 nil 值;未关闭时为 nil
  • 如果父 context 已结束(如 WithDeadline 到期),子 context 的 Err() 可能是 context.DeadlineExceeded,不是 context.Canceled
  • HTTP handler 中常需将 ctx.Err() 映射为具体 HTTP 状态码,比如 context.Canceled → 499(Client Closed Request)

goroutine 中使用 context.Value 要格外谨慎

context.WithValue 适合传入请求范围的**不可变元数据**(如 trace ID、user ID),但绝不该用来传递业务参数或可变状态。

微信公众平台开发入门教程 中文WORD版
微信公众平台开发入门教程 中文WORD版

由于微信的大热,为了更好的方便使用微信的用户查询一些信息,这篇文章是入门级的微信公众平台开发教程,需要的朋友可以参考下 这篇入门教程将引导你完成如下任务: 创建百度云平台应用启用微信公众平台开发模式获取订阅、文字、图片、语音、视频消息回复文本、图文及音乐消息程序开发

下载

容易踩的坑是把 context.Value 当成“全局变量”替代参数传递,结果导致函数签名不透明、单元测试困难、静态分析失效。

  • 值类型必须是可比较的(如 stringint、自定义 struct),且 key 类型推荐用未导出的私有类型,避免冲突
  • 不要用 string 字面量当 key,例如 ctx = context.WithValue(ctx, "user_id", 123) —— 应定义 type ctxKey string; const userIDKey ctxKey = "user_id"
  • 高并发下 WithValue 有轻微性能开销(需拷贝 map),纯性能敏感路径应避免嵌套多层

http.Server 的 Shutdown 已自动集成 context 取消

Go 1.8+ 的 http.Server.Shutdown() 内部使用 context.Context 等待活跃连接关闭,无需手动包装。

常见误区是自己再套一层 WithTimeout 并监听 Done() 来“控制 Shutdown”,反而干扰默认行为,甚至导致连接被强制中断。

  • 直接调用 srv.Shutdown(ctx) 即可,传入带超时的 context 是合理做法,但别在外部额外 select 监听
  • Shutdown 不会取消正在执行的 handler,只阻止新请求;handler 内仍需自行检查 r.Context().Done()
  • 若 handler 使用了 long poll 或 streaming,务必在循环中持续检查 ctx.Err() == nil,否则无法响应 Shutdown

并发任务取消真正难的不是调用 cancel(),而是确保每个分支、每层封装、每次 I/O 都对 ctx.Done() 做响应 —— 尤其是第三方库是否尊重 context,往往得看文档或源码。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

177

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

336

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

194

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

189

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

191

2025.06.17

C++ 高性能计算与并行编程
C++ 高性能计算与并行编程

本专题专注于 C++ 在高性能计算(HPC)与并行编程中的应用,涵盖多线程、并发数据处理、OpenMP、MPI、GPU加速等技术。通过实际案例,帮助开发者掌握 如何利用 C++ 进行大规模数据计算和并行处理,提高程序的执行效率,适应高性能计算与数据密集型应用场景。

5

2026.01.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.5万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号