当前位置: 首页 > news >正文

Golang 语言中 Context 的使用方式

一、介绍

        在Golang 语言并发编程中,经常会遇到监控 goroutine 运行结束的场景,通常我们会想使用WaitGroup 和 chan + select , 其中WaitGroup 用于监控一组goroutine 是否全部运行结束,chan + select 用于监控一个 goroutine 是否运行结束(取消一个 goroutine )

        如果我们需要监控多个goroutine 是否运行结束,或者 取消多个。通常会使用context ,当然使用context 也可以用于监控一个 goroutine 是否运行结束。

二、取消一个 goroutine

        使用context 取消一个 goroutine ,比较类似实用 chan   + select  的方式取消一个 goroutine

示例代码:

package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithCancel(context.Background())go func(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("goroutine  已停止")returndefault:fmt.Println("goroutine 正在运行")time.Sleep(time.Second)}}}(ctx)time.Sleep(time.Second * 5)cancel()time.Sleep(time.Second * 5)fmt.Println("goroutine 已结束")
}

运行结果:

        阅读上面这段代码,我们首先使用 context.Background() 创建一个context 树的根节点,然后使用context.WithCancel() 创建一个可取消的走context 类型的变量,ctx ,作为参数传递给子goroutine ,用作跟踪子goroutine 。

        然后在子 goroutine 中使用for select 监控 <- ctx.Done() 判断goroutine 是否运行结束。

        最后使用 context.Withcancel() 返回的第二个值CancelFunc 类型的cancel 变量给子goroutine 发送取消指令

三、取消多个goroutine

下面,我们再来看看一个使用context 停止多个goroutine 的示例

package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithCancel(context.Background())go worker(ctx, "节点一")go worker(ctx, "节点二")go worker(ctx, "节点三")go worker(ctx, "节点四")time.Sleep(time.Second * 5)cancel()time.Sleep(time.Second * 5)fmt.Println("main  goroutine  已结束")
}func worker(ctx context.Context, node string) {for {select {case <-ctx.Done():fmt.Println(node, "goroutine 已停止")returndefault:fmt.Println(node, "goroutine  正在运行")time.Sleep(time.Second)}}
}

运行结果:

阅读上面这段代码,我们使用go 关键字启动三个 worker goroutine ,和上个示例一样,首先创建一个context  树的节点,使用第一个返回值context 类型的字ctx  跟踪每一个worker goroutine ,在worker 中使用for select 监控 <- ctx.Done() 判断子 goroutine 是否运行结束,通过调用第二份返回值CancelFunc 类型cancel 给子goroutine 发送取消指令,此时所有字context 都会接受到取消指令,goroutine 结束运行

四、上下文信息传递

        我们在前面的示例中使用WithCancel  函数,用作取消context,除此之外,可用作取消Context 的函数还有WithDeadline 函数和WithTimeout 函数,分别用于定时取消和超时取消;在Golang中 context 包还有一个重要的作用,就是作用上下文传递,请看示例代码:

package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithCancel(context.Background())// 传递上下文信息ctxValue := context.WithValue(ctx, "uid", 1)go func(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println(ctx.Value("uid"), "goroutine 已停止")returndefault:fmt.Println("goroutine  正在运行")time.Sleep(time.Second)}}}(ctxValue)time.Sleep(time.Second * 5)cancel()time.Sleep(time.Second * 5)fmt.Println("main goroutine 已结束")}

运行结果:

        阅读上面的代码,我们使用了 WithValue 函数给子级 goroutine 传递上下文信息uid.。 WithValue 函数接收三个参数,分别是parent context ,key 和value 。返回值是一个context ,我们可以在子级 goroutine 中调用Value 方法获取传递的上下文信息。

http://www.lryc.cn/news/619084.html

相关文章:

  • 【Python 爬虫】Playwright 多浏览器支持(Chromium/Firefox/WebKit)
  • 云原生高级——nginx
  • Nginx 高级配置
  • 明远智睿T113-i核心板:工业设备制造的“破局者”
  • 10-docker基于dockerfile自动制作镜像
  • 机器学习——DBSCAN
  • imx6ull-驱动开发篇20——linux互斥体实验
  • [TryHackMe]Relevant(smb+windows令牌提权)
  • HarmonyOS元服务开发系列教程(三):实现音乐播放和封面旋转
  • 【问题解决】从Anaconda环境迁移到miniforge并在IDEA中完成环境配置
  • 【数据分享】2020-2022年我国乡镇的逐日最高气温数据(Shp/Excel格式)
  • C++动态代理技术详解:实现原理与应用场景
  • beacon-dongle系统(二)AP及Server建立
  • 双十一美妆数据分析:洞察消费趋势与行业秘密
  • 电商双 11 美妆数据分析学习报告
  • MyBatis持久层实现
  • 【前端Vue】log-viewer组件的使用技巧
  • Qwen-Image(阿里通义千问)技术浅析(一)
  • 物联网、大数据与云计算持续发展,楼宇自控系统应用日益广泛
  • [Robotics_py] 路径规划算法 | 启发式函数 | A*算法
  • Linux系统编程Day13 -- 程序地址空间
  • Seata深度剖析:微服务分布式事务解决方案
  • 微服务ETCD服务注册和发现
  • 力扣经典算法篇-50-单词规律(双哈希结构+正反向求解)
  • SQL 合并两个时间段的销售数据:FULL OUTER JOIN + COALESCE
  • 杰里平台7083G 如何支持4M flash
  • 【K8s】K8s控制器——复制集和deployment
  • 【SpringBoot】08 容器功能 - SpringBoot底层注解汇总大全
  • 4.运算符
  • [激光原理与应用-254]:理论 - 几何光学 - 自动对焦在激光器中的应用?