采用上下文取消的异步/等待模式
来源:stackoverflow
时间:2024-04-26 10:21:39 375浏览 收藏
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《采用上下文取消的异步/等待模式》,介绍一下,希望对大家的知识积累有所帮助,助力实战开发!
在我的应用程序中,我需要具有上下文取消支持的异步/等待模式。在实践中,我有一个类似的函数:
func longrunningtask() <-chan int32 { r := make(chan int32) go func() { defer close(r) // simulate a workload. time.sleep(time.second * 3) r <- rand.int31n(100) }() return r }
但是,它不支持上下文取消。为了解决这个问题,我可以添加一个参数并修改函数来等待 select 语句中的 ctx.done()
通道信号,以便在取消上下文时中止操作。
如果这样做,如果运行两次或多次,该函数将无法正确中止(因为上下文指针将被共享),因为上下文取消通道仅接收一个信号:
ctx := ... go func() { r := <-longrunningtask(ctx) } // done() works go func() { r := <-longrunningtask(ctx) } // ? // cancel() ...
以下是我对“完成”的看法:
// go/context.go 357 func (c *cancelCtx) Done() <-chan struct{} { 358 c.mu.Lock() 359 if c.done == nil { 360 c.done = make(chan struct{}) 361 } 362 d := c.done 363 c.mu.Unlock() 364 return d 365 } // Done() returns the same channel for all callers, and cancellation signal is sent once only
go 源代码是否意味着
context
并不真正支持调用其他“长时间运行”函数的函数的中止,即“链式取消”?有哪些选项可以编写异步函数来支持
.done()
使用的无限递归中的上下文取消?
解决方案
- go 源代码是否意味着上下文并不真正支持中止 a 调用其他“长时间运行”函数的函数,“链式函数” 取消”?
没有。任务可以调用其他长时间运行的任务,并沿调用链传递上下文。这是标准做法。如果上下文被取消,嵌套调用将出错并沿着调用堆栈冒出取消错误
- 有哪些选项可以编写异步函数来支持无限递归使用 .done() 时的上下文取消?
递归与采用上下文的几个嵌套调用没有什么不同。如果递归调用采用上下文输入参数并返回错误(即检查),则递归调用链将像一组非递归嵌套调用一样冒泡取消事件。
首先,让我们更新您的包装函数以支持 context.context
:
func longrunningtask(ctx context.context) <-chan int32 { r := make(chan int32) go func() { defer close(r) // workload i, err := somework(ctx) if err != nil { return } r <- i }() return r }
然后 somework
- 使用睡眠工作负载将如下所示:
func somework(ctx context.context) (int32, error) { tc := time.after(3*time.second) // fake workload // we can check this "workload" *and* the context at the same time select { case <-tc: return rand.int31n(100), nil case <-ctx.done(): return 0, ctx.err() } }
这里要注意的重要一点是,我们可以改变假“工作负载”(time.sleep),使其成为一个通道 - 从而通过 select
语句观察它和我们的上下文。大多数工作负载当然不是这么微不足道...
幸运的是,go 标准库完全支持 context.context
。因此,如果您的工作负载由大量可能长时间运行的 sql 查询组成,则可以向每个查询传递一个上下文。与 http 请求或 grpc 调用相同。如果您的工作负载由任何这些调用组成,则传入父上下文将导致任何这些潜在的阻塞调用在上下文取消时返回错误 - 因此您的工作负载将返回取消错误,让调用者知道什么发生了。
如果您的工作负载不完全适合此模型,例如计算大型曼德尔布罗特集图像。在每个像素之后检查取消的上下文可能会对性能产生负面影响,因为轮询选择不是免费的:
select { case <-ctx.Done(): // polling select when `default` is included return ctx.Err() default: }
在这种情况下,可以应用调整,如果像素以 10,000/s 的速率计算 - 每 10,000 个像素轮询一次上下文将确保任务从取消点起不晚于 1 秒返回。
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习