golang中context使用总结

一、context使用注意事项

在使用context时,有一些需要注意的事项,以及一些与性能优化相关的建议:

  1. 避免滥用context传递数据:context的主要目的是传递请求范围的数据和取消信号,而不是用于传递全局状态或大量数据。滥用context传递大量数据可能导致上下文对象变得臃肿,增加内存和GC压力。

  2. 不要修改已传递的context:传递的context是不可变的,即使在函数内部对其调用cancel方法也不会影响调用方的context。如果需要对context进行修改,应该通过返回一个新的派生context来实现。

  3. 只在需要时传递context:不要将context作为函数参数无限制地传递,而是在需要时传递。这样可以避免不必要的复杂性和代码膨胀。

  4. 及早检查取消信号:在使用context的地方,应该及早检查ctx.Done()的返回值,以尽早响应取消信号。在耗时操作前或可能阻塞的地方,应该通过select语句来监听多个操作,包括取消信号、超时和其他channel。

  5. 使用WithCancel替代WithTimeout:在可能的情况下,优先使用WithCancel函数来设置取消信号,而不是仅仅依赖于WithTimeout函数。这样可以有更精确的控制和更灵活的处理方式。

  6. 优化context的传递:在频繁调用的函数链中,避免在每个函数中重复传递相同的context,可以通过使用结构体或函数闭包将context作为参数进行传递,从而减少代码重复和提升性能。

  7. 及时取消不再需要的goroutine:如果在多个goroutine中使用context,确保在不再需要时及时取消goroutine,以避免资源浪费和潜在的goroutine泄漏。

这些注意事项和性能优化建议可帮助确保正确且高效地使用context,避免滥用和性能问题。根据具体场景和需求,可以灵活使用context的机制来优化代码的可读性、并发安全性和性能。

二、context使用举例

在这里插入图片描述

在Go语言中,context(上下文)是在不同goroutine之间传递请求范围数据、取消信号和超时处理的一种机制。下面详细介绍context的每种使用情况和相应的代码举例:

  1. 传递请求范围数据:

    package main
    
    import (
    	"context"
    	"fmt"
    )
    
    // 定义一个键类型(key)用于context中的数据传递
    type key string
    
    // 在context中设置数据
    func withValue(ctx context.Context) {
    	// 使用WithValue将数据存储在context中
    	ctxWithData := context.WithValue(ctx, key("name"), "John")
    
    	// 调用另一个函数,并将带有数据的context传递给它
    	printName(ctxWithData)
    }
    
    // 从context中获取并使用数据
    func printName(ctx context.Context) {
    	// 从context中获取数据,并进行类型断言
    	if name, ok := ctx.Value(key("name")).(string); ok {
    		fmt.Println("Name:", name)
    	}
    }
    
    func main() {
    	// 创建根context
    	ctx := context.Background()
    
    	// 传递context并设置数据
    	withValue(ctx)
    }
    

    在上面的示例中,我们定义了一个key类型,用于在context中存储数据。然后,我们使用WithValue函数将数据存储在带有数据的context ctxWithData 中,并将其传递给printName函数。在printName函数中,我们使用Value方法从context中获取数据,并进行类型断言后打印出来。

  2. 取消信号:

    package main
    
    import (
    	"context"
    	"fmt"
    	"time"
    )
    
    // 模拟一些耗时操作
    func performTask(ctx context.Context) {
    	// 检查是否接收到取消信号
    	select {
    	case <-ctx.Done():
    		fmt.Println("Task canceled")
    		return
    	default:
    		// 模拟长时间运行的任务
    		time.Sleep(5 * time.Second)
    		fmt.Println("Task completed")
    	}
    }
    
    func main() {
    	// 创建根context
    	ctx := context.Background()
    
    	// 派生子context,并设置取消信号
    	ctx, cancel := context.WithCancel(ctx)
    
    	// 启动耗时操作的goroutine,并传递带有取消信号的context
    	go performTask(ctx)
    
    	// 模拟一些操作后取消任务
    	time.Sleep(2 * time.Second)
    	cancel() // 发送取消信号
    
    	// 等待一段时间,确保程序有足够的时间处理取消信号
    	time.Sleep(1 * time.Second)
    }
    

    在上面的示例中,我们创建了一个任务函数performTask,该函数会检查是否接收到取消信号。使用context.WithCancel函数创建派生的子context,并通过调用返回的cancel函数发送取消信号。然后,我们在一个goroutine中运行任务函数,并通过传递带有取消信号的context来监听取消信号。在主goroutine中,我们等待一段时间后调用cancel函数发送取消信号。当任务函数接收到取消信号后,它会打印"Task canceled"。

  3. 超时处理:

    package main
    
    import (
    	"context"
    	"fmt"
    	"time"
    )
    
    // 模拟一些耗时操作
    func performTask(ctx context.Context) {
    	// 检查是否接收到取消信号或超时
    	select {
    	case <-ctx.Done():
    		fmt.Println("Task canceled")
    	case <-time.After(5 * time.Second):
    		fmt.Println("Task completed")
    	}
    }
    
    func main() {
    	// 创建根context
    	ctx := context.Background()
    
    	// 派生子context,并设置超时时间
    	ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
    	defer cancel()
    
    	// 启动耗时操作的goroutine,并传递带有超时设置的context
    	go performTask(ctx)
    
    	// 等待一段时间,确保程序有足够的时间处理超时或取消信号
    	time.Sleep(5 * time.Second)
    }
    

    在上面的示例中,我们创建了一个任务函数performTask,该函数会检查是否接收到取消信号或超时。使用context.WithTimeout函数创建派生的子context,并通过调用返回的cancel函数来设置超时时间。然后,我们在一个goroutine中运行任务函数,并传递带有超时设置的context来监听超时或取消信号。在主goroutine中,我们等待一段时间以确保程序有足够的时间处理超时或取消信号。当超过超时时间后,任务函数会打印"Task canceled"。

这些是context在Go语言中的常见用法,它们使得在并发环境中处理请求范围数据、取消信号和超时变得更加简单和可靠。根据具体的使用场景,你可以选择适当的context函数来创建和传递context,并根据需要进行取消和超时处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/146905.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SARAS算法

SARAS算法 代码仓库:https://github.com/daiyizheng/DL/tree/master/09-rl Sarsa算法是一种强化学习算法&#xff0c;用于解决马尔可夫决策过程&#xff08;MDP&#xff09;问题。它是一种基于值函数的方法&#xff0c;可以用于学习最优策略。本文将介绍Sarsa算法的流程。 S…

汽车以太网IOP测试新利器

IOP测试目的 汽车以太网物理层IOP&#xff08;Interoperability &#xff09;测试&#xff0c;即测试被测对象以太网物理层之间的互操作性。用于验证车载以太网PHY能否在有限时间内建立稳定的链路&#xff1b;此外&#xff0c;还用于验证车载以太网PHY可靠性相关的诊断特性&am…

滚雪球学Java(63):Java高级集合之TreeSet:什么是它,为什么使用它?

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

Java Elasticsearch 按一定时间间隔(timeInterval)循环查询数据

最近有个需求&#xff0c;前端传入时间间隔&#xff0c;去elasticsearch按照时间间隔统计每个时间间隔内数据量。 public List<HashMap<String,Object>> getCount(RequestParam Integer time, RequestParam String selectedDatedTime) {SimpleDateFormat format n…

Karmada调度器

调度器就像一个发动机&#xff0c;如果没有了发动机输入动力&#xff0c;是无法正常运行的。就像 Kubernetes 的调度器&#xff0c;它会负责根据节点的资源状态、Pod 的运行状态&#xff0c;判断 Pod 是调度到怎样的集群节点上去。对于 Karmada 这样的多云能力的调度器来说&…

Webpack 性能优化 二次编译速度提升3倍!

本文作者为 360 奇舞团前端开发工程师 Rien. 本篇文章主要记录 webpack 的一次性能优化。 现状 随着业务复杂度的不断增加&#xff0c;项目也开始变得庞大&#xff0c;工程模块的体积也不断增加&#xff0c;webpack 编译的时间也会越来越久&#xff0c;我们现在的项目二次编译的…

【fbtft】如何添加fbtft驱动

获取lcd ic的datasheet&#xff0c;或者直接找到其他平台&#xff08;linux&#xff0c;stm32&#xff0c;esp32&#xff09;的驱动 我用的是合宙的esp32驱动&#xff0c;注意是c语言的&#xff0c;合宙上层用lua封装了&#xff0c;需要找到sdk源码。 源码路径&#xff1a; …

2021年09月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 如下图所示,小明想要做一个文字逐字出现的动画效果,他画出了程序的流程图,以下哪个程序可以实现? A: B: C: D: 答案&#

代号:408 —— 1000道精心打磨的计算机考研题

文章目录 &#x1f4cb;前言&#x1f3af;计算机科学与技术专业介绍&#xff08;14年发布&#xff09;&#x1f9e9;培养目标&#x1f9e9;毕业生应具备的知识和能力&#x1f9e9;主要课程 &#x1f3af;代号&#xff1a;408&#x1f525;文末送书&#x1f9e9;有什么优势&…

干货 | Elasticsearch 8.11 ES|QL 初体验

这里没有理论&#xff0c;只有验证后的结论和体验。 前提&#xff1a;这是 8.11 版本的新功能&#xff0c;必须提前安装最新 8.11 版本。 1、对比参考实现 1.1 DSL 原始语法 POST kibana_sample_data_ecommerce/_search 1.2 ES|QL 检索语法&#xff0c; 类似SQL实现 POST /_que…

2023亚太杯数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

机器学习—基本术语

目录 1.样本&#xff08;示例&#xff09; 2.属性 3.属性值 4.属性空间 5.样本空间 6.学习&#xff08;训练&#xff09; 7.数据集 8.测试 9.假设 10.学习器 11.标记 12.样例 13.标记空间&#xff08;样例空间&#xff09; 14.分类与回归 15.有监督学习、无监督…

GZ038 物联网应用开发赛题第5套

2023年全国职业院校技能大赛 高职组 物联网应用开发 任 务 书 &#xff08;第5套卷&#xff09; 工位号&#xff1a;______________ 第一部分 竞赛须知 一、竞赛要求 1、正确使用工具&#xff0c;操作安全规范&#xff1b; 2、竞赛过程中如有异议&#xff0c;可向现场考评…

城市内涝对策,万宾科技内涝积水监测仪使用效果

随着城市化进程的加速&#xff0c;城市道路积水问题明显越来越多&#xff0c;给人们的出行和生活带来更多的不便。内涝积水监测仪作为高科技产品能够实时监测道路积水情况&#xff0c;为城市排水系统的管理和维护提供重要的帮助。 在城市生命线的基础设施规划之中&#xff0c;地…

Spring Cloud

1. 服务拆分和远程调用 任何分布式架构都离不开服务的拆分&#xff0c;微服务也一样。服务拆分&#xff1a;一个单体架构按照功能模块进行拆分&#xff0c;变成多个服务。 微服务需要根据业务模块拆分&#xff0c;做到单一职责&#xff0c;不要重复开发相同业务。 1.1 服务…

【论文阅读】(CGAN)Conditional Generative Adversarial Nets

论文地址&#xff1a;[1411.1784] Conditional Generative Adversarial Nets (arxiv.org) - 条件生成式对抗网络&#xff1b; 解读&#xff1a; 这篇论文中的Conditional GAN和原生GAN在结构上没有太大差别&#xff0c;时间也是紧随着原生GAN出来的&#xff0c;它的思想应该后…

理解Vue源码,从0开始撸了一个简版Vue

vue 的双向绑定、虚拟dom、diff算法等等面试常见问题你可能在几年前就学过了&#xff0c;其中有些人可能看过Vue的源码&#xff0c;了解过Vue是如何实现数据监听和数据绑定这些技术的。不过让从零开始实现一个 vue&#xff0c;你可以吗? 模板语法其实早就存在&#xff0c;在V…

03-学成在线内容管理模块之课程查询

课程查询 需求分析 教学机构人员点击课程管理按钮进入课程查询界面,在课程列表页面输入查询条件查询课程的信息 当不输入查询条件时默认会全部课程信息,输入查询条件会查询符合条件的课程信息,约束条件是本教学机构查询本机构的课程信息 数据模型(model工程) 课程查询功能…

MAT工具定位分析Java堆内存泄漏问题方法

原创/朱季谦 一、MAT概述与安装 MAT&#xff0c;全称Memory Analysis Tools&#xff0c;是一款分析Java堆内存的工具&#xff0c;可以快速定位到堆内泄漏问题。该工具提供了两种使用方式&#xff0c;一种是插件版&#xff0c;可以安装到Eclipse使用&#xff0c;另一种是独立版…

论文浅尝 | 用于开放式文本生成的事实增强语言模型

笔记整理&#xff1a;李煜&#xff0c;东南大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://proceedings.neurips.cc/paper_files/paper/2022/hash/df438caa36714f69277daa92d608dd63-Abstract-Conference.html 1. 动机 生成式语言模型&#xff08;例如 GPT-3…