学习笔记-Golang中的Context
文章目录
- 1、什么是Context
- 2、Context的作用
- 3、Context的解析
- 3.1、Context的源码解析
- 3.2、 context包中实现context接口的四种结构体类型
- 3.2.1、emptyCtx
- 3.2.2、cancelCtx
- 3.2.3、timerCtx
- 3.2.4、valueCtx
- 4、总结
1、什么是Context
Context是 Go 语言中的一个标准库,用于在处理并发编程时,提供对请求的截止时间、取消信号以及请求范围内共享数据的管理。它在多个 goroutine 之间传递,是一种上下文管理工具。
Context 的主要目的是在不同的 goroutine 之间传递控制信号和数据。通过 Context,你可以:
- 设置请求的超时时间或截止时间。
- 传递取消信号,以便可以通知 goroutine 任务已经完成或需要停止。
- 在多个 goroutine 之间共享值。
2、Context的作用
设想这样一种场景:你正在开发一个 Web 应用,当用户发送一个请求(request)后,可能会启动多个 goroutine 来处理该请求的不同部分。如果单个请求的 goroutine 结构比较简单,处理起来也不麻烦,但是如果启动多个、深层次的 goroutine,则会导致代码的复杂性和可维护性变得更加困难。而有了context,我们就可以通过它来管理这些 goroutine,并在它们之间传递控制信号和数据。
Context 在这种场景中的作用主要体现在以下几个方面:
- 取消信号传递:处理用户请求的过程中,可能会因为用户主动取消请求或请求超时而需要提前停止某些 goroutine 的执行。Context 提供了一种机制,可以在多个 goroutine 之间传递取消信号,当父 Context 取消时,所有与之关联的子 goroutine 都会收到取消通知并可以安全地停止工作,避免不必要的资源消耗。
- 数据共享:在处理用户请求时,某些全局信息(例如用户认证信息、追踪 ID 等)需要在不同的 goroutine 之间共享。通过 Context,这些数据可以被安全地传递,而不需要通过全局变量或其他不安全的方式共享。这样可以保持代码的简洁性和安全性,尤其在并发环境下避免数据竞争。
- 超时控制:在处理用户请求时,可能会遇到一些耗时长的操作,例如数据库查询或网络请求。Context 提供了一种机制,可以设置超时时间,当超时时间到达后,Context 会自动取消相关的 goroutine,避免资源占用过多。
除了上述作用外,Context 还可以更高效地管理系统资源,例如在请求超时或任务完成时主动释放资源,避免资源浪费,防止 goroutine 泄漏。
3、Context的解析
3.1、Context的源码解析
Context 实际上是一个定义了4个方法的接口,凡是实现了该接口的都称为一种 Context。
type Context interface {// 返回 context 的截止时间(deadline),表示任务应该在什么时候之前完成。// 如果没有设置截止时间,就返回 false 和一个空的时间值。Deadline() (deadline time.Time, ok bool)//当 context 被取消或者超时时,这个方法返回的 channel 会被关闭。通过监听这个信号,可以决定是否要终止正在进行的任务。Done() <-chan struct{}//这个方法用来返回 context 被取消的具体原因,比如是因为超时、手动取消等,通常会在 Done() 关闭后使用。Err() error// 从 context 中获取与某个 key 关联的数据,用于在 goroutine 之间传递一些共享信息。// key 可以是任何类型,用于区分不同的数据。Value(key interface{}) interface{}
}
3.2、 context包中实现context接口的四种结构体类型
在context
包中,有四个结构体类型实现了Context接口,分别是emptyCtx
、cancelCtx
、timerCtx
和valueCtx
。
3.2.1、emptyCtx
emptyCtx
是一个没有任何取消、截止时间或值的 Context,它通常作为默认的上下文,在创建顶级 Context 时使用。
解释:
emptyCtx
实现了 Context 接口的所有方法,但它们都返回默认值或 nil,因此
emptyCtx`是没有实际功能的。那么它存在的目的是什么呢?
原因是,在 Go 的 Context 体系中,Context 对象通常是分层次的,即通过创建一个父 Context 来衍生出子 Context,并在这些子 Context 中传递控制信号、共享数据等。因此,为了构建这棵 Context 对象树,我们需要一个基础的、没有任何附加信息的根节点。emptyCtx 正是为了提供这样一个基本的起点。
此外,有时你在编写代码时需要一个 Context 占位符,但暂时不确定具体的 Context 类型。这时你可以使用 context.TODO(),它返回的实际上也是 emptyCtx。这样可以让代码先运行,稍后再决定具体的 Context 实现。
总之,emptyCtx
是一个没有任何功能的 Context,它的使用场景有两个:
- 用于顶层上下文,作为 Context 对象树的根节点。
- 作为占位符,用于在编写代码时暂时不确定具体的 Context 类型。
注意:这四种结构体中,只有emptyCtx
不需要通过已有context
实例创建,因此一个context树的根context一定是emptyCtx
。
使用示例:
ctx := context.Background()
// 或者
ctx := context.TODO()
// 以下代码中,ctx 就是一个空的上下文
3.2.2、cancelCtx
cancelCtx
是带有取消功能的 Context,它允许父 Context 取消,并通知所有子 Context 和相关 goroutine。
解释:
- cancelCtx 通过 WithCancel 函数创建,提供一种手动取消 Context 的机制。当调用 cancel() 函数时,所有依赖此 Context 的子 goroutine 都会收到取消通知。
- Done() 方法会返回一个关闭的 channel,表示 Context 已经被取消。
使用场景:
- 用于主动取消某个操作,比如超时、用户主动取消等。
- 适用于请求处理被取消、提前终止任务等场景。
使用示例:
package mainimport ("context""fmt""time"
)func main() {// 通过emptyCtx创建一个带有取消功能的上下文(context.Background()创建的即为emptyCtx)ctx, cancel := context.WithCancel(context.Background())go func() {// 模拟执行任务for {select {case <-ctx.Done(): // 接收到取消信号,退出 goroutinefmt.Println("Task canceled")returndefault:fmt.Println("Task running...")time.Sleep(1 * time.Second)}}}()// 运行 3 秒后取消操作time.Sleep(3 * time.Second)cancel()// 给 goroutine 充分的时间来处理取消操作time.Sleep(1 * time.Second)
}
注意:当 Done() 信号触发时,虽然上下文 Context 已经被取消,但具体的 goroutine 或子进程是否终止,取决于代码逻辑。cancel() 只是通知 goroutine Context 已被取消,具体的退出逻辑需要我们手动处理。
3.2.3、timerCtx
timerCtx
是带有超时或截止时间(Deadline)的 Context,当超过指定时间时,Context 会自动取消。
解释:
timerCtx
是通过WithTimeout
或WithDeadline
创建的。它允许你为 Context 设置一个时间限制,当超时或达到截止时间时,Context 会自动取消,所有关联的 goroutine 都会收到取消通知。- 主要用于那些有执行时间限制的任务。
使用场景:
- 当你需要控制某个任务的最大执行时间(如网络请求、数据库操作等),防止任务无限期地运行时,使用 timerCtx。
- 适用于设置请求超时、操作超时等场景。
使用示例:
// // 通过emptyCtx创建一个带有取消功能的上下文(context.Background()创建的即为emptyCtx)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()select {
case <-time.After(3 * time.Second):fmt.Println("Task finished")
case <-ctx.Done():fmt.Println("Timeout:", ctx.Err()) // 这里会输出超时的错误
}
3.2.4、valueCtx
valueCtx
是可以在 goroutine 之间传递键值对的 Context,用于携带与请求相关的信息。context.WithValue() 可以将特定的值与某个 key 关联起来,并且这个 key 通常是一个自定义类型,而不是直接使用内置的 string 或 int 类型。
解释:
valueCtx
是通过 WithValue
创建的,用于在不同的 goroutine 之间传递一些与上下文相关的数据。这个数据可以通过 Context 的Value()
方法获取。 context.WithValue()
可以将特定的值与某个 key
关联起来,并且这个 key
通常是一个自定义类型,而不是直接使用内置的数据类型,如string
或 int
类型。
使用场景:
- 适用于在多个 goroutine 之间传递一些共享信息,如用户 ID、请求 ID 等。
- 避免使用全局变量或复杂的依赖传递,确保上下文中的数据和 goroutine 的生命周期一致。
使用示例:
type key stringfunc main() {ctx := context.WithValue(context.Background(), key("userID"), 123)go func(ctx context.Context) {userID := ctx.Value(key("userID")) // 定义了一个新的类型 key,底层类型为 stringfmt.Println("User ID:", userID)}(ctx)time.Sleep(1 * time.Second)
}
注意:在上述代码中,如果直接使用 string
类型作为 key
,很可能会出现 key
重名的情况。比如,不同的模块可能会不小心使用相同的字符串 “userID” 作为 key
,这会导致冲突。因此,为了避免这种情况,我们会创建一个自定义类型的 key
,比如 type key string
。这样,尽管它本质上仍然是字符串类型,但它已经是一个新的类型,这样就避免了潜在的冲突问题。
4、总结
Context 是 Go 语言中的一个标准库,用于在处理并发编程时,提供对请求的截止时间、取消信号以及请求范围内共享数据管理的管理。它在多个 goroutine 之间传递,是一种上下文管理工具。
通过context包给出的四种结构体类型,我们可以轻松实现对 goroutine 的管理:
emptyCtx
:基础的空 Context,没有取消、超时或值,适合作为顶层 Context 使用。cancelCtx
:提供手动取消功能,适合需要手动控制任务生命周期的场景。timerCtx
:带有超时或截止时间,适合限制任务执行时间的场景。valueCtx
:允许传递数据,适合跨 goroutine 传递少量与请求相关的上下文信息。
相关文章:
学习笔记-Golang中的Context
文章目录 1、什么是Context2、Context的作用3、Context的解析3.1、Context的源码解析3.2、 context包中实现context接口的四种结构体类型3.2.1、emptyCtx3.2.2、cancelCtx3.2.3、timerCtx3.2.4、valueCtx 4、总结 1、什么是Context Context是 Go 语言中的一个标准库࿰…...

ArrayList 源码解析
ArrayList是Java集合框架中的一个动态数组实现,提供了可变大小的数组功能。它继承自AbstractList并实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同…...
libgit2编译
1. 源码下载 libgit2源码下载 2. 编译要求 CMake下载 CMake教程 3. 编译步骤 Prerequisites Make sure CMake on your %PATH% Build Create a build directory beneath the libgit2 source directory, and change into it: mkdir build && cd buildCreate the …...
mac新手入门(快捷键)
系统常用快捷键 基本操作 Command-Z 撤销Command-X 剪切 Command-C 拷贝(Copy) Option Shift Command V 纯文本拷贝 Command-V 粘贴 Command-A 全选(All)Command-S 保存(Save) Command-F 查找࿰…...
curl 的使用详解
curl 是一个非常强大的命令行工具,用于通过各种协议(如 HTTP、HTTPS、FTP 等)传输数据。它广泛应用于测试 API、下载文件、调试网络请求等。 下面是 curl 常用功能的详解及示例: 基本语法 curl [options] [URL]1. 基本请求 发起…...

从基础到进阶:利用EasyCVR安防视频汇聚平台实现高效视频监控系统的五步走
随着科技的飞速发展,视频监控技术在社会安全、企业管理、智慧城市构建等领域扮演着越来越重要的角色。一个高效智能的视频监控管理系统不仅能够提升监控效率,还能在预防犯罪、事故预警、数据分析等方面发挥巨大作用。 一、需求分析 在设计视频监控管理…...

CORS漏洞及其防御措施:保护Web应用免受攻击
1. 背景- 什么是CORS? 在当今互联网时代,Web 应用程序的架构日益复杂。一个后端服务可能对应一个前端,也可能与多个前端进行交互。跨站资源共享(CORS)机制在这种复杂的架构中起着关键作用,但如果配置不当&…...

C语言自定义类型结构体(24)
文章目录 前言一、结构体类型的声明结构体回顾结构体的特殊声明结构体的自引用 二、结构体的内存对齐对齐规则为什么存在内存对齐?修改默认对齐数 三、结构体传参四、结构体实现位段什么是位段位段的内存分配位段的跨平台问题位段的应用位段使用的注意事项 总结 前言…...

补题篇--codeforces
传送门:Problem - 1881C - Codeforces 题目大意: 思路: 首先解决这个问题要知道 一个 ( x , y ) 顺时钟旋转 90 , 180 , 270可以得到 ( y , n - x 1 ) , ( n - x 1 , n - y 1 ) ,( n - y …...
【字幕】恋上数据结构与算法之015动态数组03简单接口的实现
我们先来看一下,不要着急啊大家不要着急,这些东西我肯定会一点一点会给大家去实现,最终实现到跟Java官方版本差不多,只要我们自己实现了,偶尔类似的,你会发现你倒回去看Java官方的那个源码,你会…...
基于2023年网络赛赛题了解OpenCv
一、OpenCv图像读取与显示 1.图像的读取与显示 cv.imread() 图像读取,第一个参数是照片的位置一般是完整路径,第二个参数是指定图片输出的样式 cv.IMREAD_COLOR: 加载彩色图像。任何图像的透明度都会被忽视。(默认模式)。cv.I…...
你到底更适合买虚拟主机还是服务器?
前言 在当今数字化的时代,选择合适的网络服务平台对于个人和企业来说至关重要。无论是搭建个人博客、运营企业网站还是开发游戏,服务器的选择都会直接影响到项目的成本、性能以及用户体验。那么,你到底适合虚拟主机还是服务器呢?…...
linux手册翻译 addr2line
名称 addr2line 将地址转换为文件名和代码行数 简介 addr2line [-a|--addresses][-b bfdname|--targetbfdname][-C|--demangle[style]][-r|--no-recurse-limit][-R|--recurse-limit][-e filename|--exefilename][-f|--functions] [-s|--basename][-i|--inlines][-p|--pretty-…...

python-素数中的等差数列
题目描述 质数是在数论中很有意思的数,有很多题都可以围绕它来出,就如你眼前所见的这道题。 给定一个闭区间 [a,b] ,将此范围内的所有素数进行从小到大排序,对于连续的素数,我们可以发现很多等差数列(元素个数大于等于 3 )&#x…...
Unity3D 服务器AStar寻路客户端位置同步显示验证详解
在游戏开发中,经常需要在服务器和客户端之间同步玩家的位置信息,以便其他玩家可以看到他们的移动。本文将详细介绍如何在Unity 3D中使用AStar算法进行路径规划,并在服务器和客户端之间同步玩家的位置信息。 对惹,这里有一个游戏开…...
无人机之悬停精度篇
无人机的悬停精度是指无人机在无GPS信号或其他外部定位辅助下,能够保持在一个固定空间位置时的精度。这一精度受到多种因素的影响,包括但不限于风速、气压、温度、湿度以及无人机自身的姿态稳定性等。以下是对无人机悬停精度的详细分析: 一、…...

力扣题解2848
大家好,欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述(简单): 与车相交的点 给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i,nums[i] [starti, endi] &…...

电子电气架构---智能汽车应该是怎么样的架构?
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不…...

无心剑七绝《中秋相思》
七绝中秋相思 中秋月满意深长 百代江阳老窖香 莫道天涯情不尽 相思寸寸赋华章 2023年9月29日 平水韵七阳平韵 这首诗七绝《中秋相思》由无心剑所作,以其深情的笔触描绘了中秋夜的相思之情。 诗中首句“中秋月满意深长”即以中秋圆月为起点,勾勒出了一幅…...

Python画笔案例-051 绘制赵爽弦图
1、绘制赵爽弦图 通过 python 的turtle 库绘制 赵爽弦图,如下图: 2、实现代码 绘制 赵爽弦图,以下为实现代码: """赵爽弦图.py本程序演录了如何自定义形状,如何把它添加到造型字典。赵爽弦图是用来证明…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...