【Go】context标准库

文章目录

  • 1. 概述
    • 1.1 什么是 Context
    • 1.2 设计原理
    • 1.3 使用场景
    • 1.4 Context 分类
      • 核心:Context接口
  • 2. 源码解读
    • 4个实现
      • emptyCtx
        • TODO 和 Background
      • cancelCtx
        • WithCancel
          • cancelCtx.propagateCancel 构建父子关联
          • parentCancelCtx 获取父上下文中的内嵌cancelCtx
        • cancel
      • timerCtx
        • WithTimeout 和 WithDeadline
          • timerCtx.cancel
      • WithValue
  • 3. 总结
  • 4. 参考

1. 概述

基于版本: go1.22.3/src/context/context.go

1.1 什么是 Context

上下文 context.Context在Go 语言中用来设置截止日期、同步信号,传递请求相关值的结构体。上下文与 Goroutine 有比较密切的关系,是 Go 语言中独特的设计,在其他编程语言中我们很少见到类似的概念。

主要用于超时控制和多Goroutine间的数据传递。

看一下官方定义

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.
Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled.

  • Package context defines the Context type:Go语言中的context包定义了一个名为Context的类型。

  • which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes:Context类型用于在API边界之间以及不同进程之间传递诸如截止时间(deadlines)、取消信号(cancellation signals)和其他请求作用域内的值。

  • Incoming requests to a server should create a Context:当服务器接收到一个请求时,应该创建一个Context。

  • and outgoing calls to servers should accept a Context:当服务器向外发起调用时,应该接受一个Context。

  • The chain of function calls between them must propagate the Context:在这些函数调用链中,必须传递Context。

  • optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue:可以选择用WithCancel、WithDeadline、WithTimeout或WithValue方法创建的派生Context替换原有的Context。

  • When a Context is canceled, all Contexts derived from it are also canceled:当一个Context被取消时,所有从它派生出来的Context也会被取消。

简而言之,context包和Context类型在Go语言中用于控制请求的生命周期,包括传递截止时间、取消信号等信息,并确保这些信息能够在服务器之间的函数调用链中传递。当需要取消请求时,所有相关的Context都会被取消,这样可以优雅地终止请求处理。

1.2 设计原理

因为context.Context主要作用就是进行超时控制,然后外部程序监听到超时后就可以停止执行任务,取消 Goroutine。

网上有很多用 Context 来取消 Goroutine 的字眼,初学者(比如笔者)可能误会,以为 Context 可以直接取消 Goroutine。

实际,Context 只是完成了一个信号的传递,具体的取消逻辑需要由程序自己监听这个信号,然后手动处理。

Go 语言中的 Context 通过构建一颗 Context 树,从而将没有层级的 Goroutine 关联起来。

在超时或者手动取消的时候信号都会从最顶层的 Goroutine 一层一层传递到最下层。这样该 Context 关联的所有 Goroutine 都能收到信号,然后进入自定义的退出逻辑。

在这里插入图片描述

比如这里手动取消了 ctxB1,然后 ctxB1的两个子ctx(C1和C2)也会收到取消信号,这样3个Goroutine都能收到取消信号进行退出了。

1.3 使用场景

最常见的就是 后台 HTTP/RPC Server。

在 Go 的 server 里,通常每来一个请求都会启动若干个 goroutine 同时工作:有些去数据库拿数据,有些调用下游接口获取相关数据,具体如下图:
在这里插入图片描述

而客户端一般不会无限制的等待,都会被请求设定超时时间,比如100ms。

比如这里GoroutineA消耗80ms,GoroutineB3消耗30ms,已经超时了,那么后续的GoroutineCDEF都没必要执行了,客户端已经超时返回了,服务端就算计算出结果也没有任何意义了。

所以这里就可以使用 Context 来在多个 Goroutine 之间进行超时信号传递。

同时引入超时控制后有两个好处:

  • 1)客户端可以快速返回,提升用户体验
  • 2)服务端可以减少无效的计算

1.4 Context 分类

Context 在 Go 1.7 版本引入标准库中,主要内容可以概括为:

  • 1 个接口
    • Context
  • 4 种实现
    • emptyCtx
    • cancelCtx
    • timerCtx
    • valueCtx
  • 6 个方法
    • Background
    • TODO
    • WithCancel
    • WithDeadline
    • WithTimeout
    • WithValue

核心:Context接口

Context 它是一个接口,定义了几个方法:

type Context interface {// 如果返回 ok==false 则表示没有设置Deadline时间Deadline() (deadline time.Time, ok bool)// Done():返回一个只读chan,如果可以从该 chan 中读取到数据,则说明 ctx 被取消了Done() <-chan struct{}// 如果ctx没有被取消,返回nil;如果是,则返回相应的原因(错误类型)Err() error// 用于储存一些键值对。要注意使用类型断言。Value(key interface{}) interface{}
}

2. 源码解读

4个实现

context 包的核心是 context.Context 接口,另外有四个 struct 实现了 Context 接口,分别是

  • emptyCtx,
  • cancelCtx
  • timerCtx
  • valueCtx,

其中 emptyCtx 是一个默认的空结构体,其余三个都是在其基础上添加了各自功能的实现,针对 emptyCtx ,context 包中暴露了两个方法 Background()TODO() 去创建一个空的 emptyCtx

而针对后面三种具体的 struct ,context 包总共暴露了四个方法去产生对应的 struct, 他们分别是: WithCancel(), WithDeadLine(), WithTimeout(), WithValue(),对应关系如下:

在这里插入图片描述

emptyCtx

// emptyCtx 过空方法实现了 context.Context 接口,它没有任何功能。
type emptyCtx intfunc (*emptyCtx) Deadline() (deadline time.Time, ok bool) {return
}func (*emptyCtx) Done() <-chan struct{} {return nil
}func (*emptyCtx) Err() error {return nil
}func (*emptyCtx) Value(key interface{}) interface{} {return nil
}
TODO 和 Background

TODO 和 Background 方法用来返回一个 emptyCtx 类型,他们在实现上都一样:

var (background = new(emptyCtx)todo       = new(emptyCtx)
)func Background() Context {return background
}func TODO() Context {return todo
}

从源代码来看,context.Backgroundcontext.TODO和也只是互为别名,没有太大的差别,只是在使用和语义上稍有不同:

  • context.Background 是上下文的默认值,所有其他的上下文都应该从它衍生出来;
  • context.TODO 应该仅在不确定应该使用哪种上下文时使用;

在多数情况下,如果当前函数没有上下文作为入参,我们都会使用 context.Background 作为起始的上下文向下传递。

cancelCtx

这是一个带 cancel 功能的 context。

type cancelCtx struct {Contextmu       sync.Mutex            // 用于同步done     chan struct{}         // 会在 Done 中返回children map[canceler]struct{} // 子上下文列表,done 被关闭后,会遍历这个 map,关闭所有的子上下文err      error                 // 关闭 chan 产生的异常,在初始化时会被赋值使不为空

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决 vue3 中 echarts图表在el-dialog中显示问题

原因&#xff1a; 第一次点开不显示图表&#xff0c;第二次点开虽然显示图表&#xff0c;但是图表挤在一起&#xff0c;页面检查发现宽高只有100px,但是明明已经设置样式宽高100% 这可能是由于 el-dialog 还没有完全渲染完成&#xff0c;而你的 echarts 组件已经开始尝试渲染图…

计算机网络习题( 第3章 物理层 第4章 数据链路层 )

第3章 物理层 一、单选题 1、下列选项中&#xff0c;不属于物理层接口规范定义范畴的是&#xff08; &#xff09;。 A、 接口形状 B、 引脚功能 C、 传输媒体 D、 信号电平 正确答案&#xff1a; C 2、在物理层接口特性中&#xff0c;用于描述完成每种功能的事件发…

通俗易懂!使用Excel和TF实现Transformer

本文旨在通过最通俗易懂的过程来详解Transformer的每个步骤&#xff01; 假设我们在做一个从中文翻译到英文的过程&#xff0c;我们的词表很简单如下&#xff1a; 中文词表&#xff1a;[机、器、学、习] 英文词表[deep、machine、learning、chinese] 先来看一下Transformer的…

智慧楼盘二维、三维组件融合 720三维全景可视化

本系统通过数字孪生技术&#xff0c;实现小区楼盘系统的可视化展示&#xff0c;整合楼盘内各个系统的数据源&#xff0c;将楼盘模型与房间模型、720三维全景图相结合&#xff0c;实现了从楼盘周边到室内布局的全方位展示&#xff0c;为购房者提供全方位的可视化信息。 整个项目…

QT QCombox QSS样式问题

/*combobox 样式*/ QComboBox#FileterComboBox,QComboBox#DateRangeComboBox{background-color: #262626; /* 背景颜色 */color: #e0e0e0; /* 文本颜色 */border-radius:16px;font-family: "Microsoft YaHei"; /* 文本字体族 */font-size: 18px; /* 文…

Unittest02|TestSuite、TestRunner、HTMLTestRunner、处理excel表数据、邮件接收测试结果

目录 八、测试套件TestSuite和测试运行器TestRunner 1、基本概念 2、创建和使用测试套件 3、 自动发现测试用例、创建测试套件、运行测试 4、生成html的测试报告&#xff1a;HTMLTestRunner 1️⃣导入HTMLTestRunner模块 2️⃣运行测试用例并生成html文件 九、unittest…

NIPS2014 | GAN: 生成对抗网络

Generative Adversarial Nets 摘要-Abstract引言-Introduction相关工作-Related Work对抗网络-Adversarial Nets理论结果-Theoretical Results实验-Experiments优势和不足-Advantages and disadvantages缺点优点 结论及未来工作-Conclusions and future work研究总结未来研究方…

【已解决】pyinstaller打包ico图片报错:OSError: [WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。

起因&#xff1a; pyinstaller加上 --icon 参数打包时报错。 命令如下&#xff1a; 解决&#xff1a; 关闭 Windows 的病毒防护即可&#xff0c;步骤如下。 点屏幕右下角通知栏&#xff0c;进入“病毒和威胁防护”&#xff1a; 打开&#xff1a; 关闭实时保护&#xff08…

011-spring-整合三方框架的命名空间原理(重要)

根据context标签来学习了解 <context:property-placeholder location"jdbc.properties"/> <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource"><property name"driver" value"${db.driver}&quo…

No.29 笔记 | CTF 学习干货

大家好呀&#xff01;我刚参加了美国线上CTF比赛&#xff0c;收获超多&#xff0c;特别感谢老师教我的干货知识。今天就和大家分享我的学习笔记。CTF像刺激冒险&#xff0c;有挑战有惊喜。 学习中我懂了很多知识技能&#xff0c;像密码学、Web安全、Misc题型等&#xff0c;它们…

sonarqube 安装及使用

一、官网参考地址 相关版本下载地址 配置全局变量 .bash_profileexport SONAR_HOME=/Users/jd/soft/sonar-scanner-6.2.1.4610 export PATH=$PATH:$SONAR_HOME/bin export SQ_HOST=http://127.0.0.1:9000/ export SQ_TOKEN=squ_dbb1913e095a92a727a918a9ba6b1af94b007748二、…

使用ArcGIS/ArcGIS pro绘制六边形/三角形/菱形渔网图

在做一些尺度分析时&#xff0c;经常会涉及到对研究区构建不同尺度的渔网进行分析&#xff0c;渔网的形状通常为规则四边形。构建渔网的方法也很简单&#xff0c;使用ArcGIS/ArcGIS Pro工具箱中的【创建渔网/CreateFishnet】工具来构建。但如果想构建其他形状渔网进行相关分析&…

pytorch MoE(专家混合网络)的简单实现。

专家混合&#xff08;Mixture of Experts, MoE&#xff09;是一种深度学习模型架构&#xff0c;通常用于处理大规模数据和复杂任务。它通过将输入分配给多个专家网络&#xff08;即子模型&#xff09;&#xff0c;然后根据门控网络&#xff08;gating network&#xff09;的输出…

NAT 技术如何解决 IP 地址短缺问题?

NAT 技术如何解决 IP 地址短缺问题&#xff1f; 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 随着互联网的普及和发展&#xff0c;IP 地址的需求量迅速增加。尤其是 IPv4 地址&…

华为麦芒5(安卓6)termux记录 使用ddns-go,alist

下载0.119bate1版,不能换源,其他源似乎都用不了,如果root可以直接用面具模块 https://github.com/termux/termux-app/releases/download/v0.119.0-beta.1/termux-app_v0.119.0-beta.1apt-android-5-github-debug_arm64-v8a.apk 安装ssh(非必要) pkg install openssh开启ssh …

FPC在蓝牙耳机中有哪些应用?【新立电子】

随着科技的进步和消费者需求的提升&#xff0c;耳机已经从传统的有线连接转变为现在的无线蓝牙耳机&#xff0c;真正做到了便捷出行与极佳的用户体验。而FPC在蓝牙耳机中的应用主要体现在优化耳机的设计与性能上。 蓝牙耳机&#xff0c;主要使用方式是与手机、电脑等移动设备通…

《计算机组成及汇编语言原理》阅读笔记:p121-p122

《计算机组成及汇编语言原理》学习第 8 天&#xff0c;p121-p122 总结&#xff0c;总计 2 页。 一、技术总结 1.memory优化 (1)cache memory remove blank from “Most computers support two different kinds (levels) of cache: level one (L1) cache is built into the …

ffmpeg: stream_loop报错 Error while filtering: Operation not permitted

问题描述 执行ffmpeg命令的时候&#xff0c;报错&#xff1a;Error while filtering: Operation not permitted 我得命令如下 ffmpeg -framerate 25 -y -i /data/workerspace/mtk/work_home/mtk_202406111543-l9CSU91H1f1b3/tmp/%08d.png -stream_loop -1 -i /data/workerspa…

【微信小程序】1|底部图标 | 我的咖啡店-综合实训

底部图标 引言 在微信小程序开发中&#xff0c;底部导航栏&#xff08;tabBar&#xff09;是用户界面的重要组成部分&#xff0c;它为用户提供了快速切换不同页面的功能。今天&#xff0c;我们将通过一个实际案例——“我的咖啡店”小程序&#xff0c;来详细解析如何配置底部图…

c++编译过程初识

编译过程 预处理&#xff1a;主要是执行一些预处理指令&#xff0c;主要是#开头的代码&#xff0c;如#include 的头文件、#define 定义的宏常量、#ifdef #ifndef #endif等条件编译的代码&#xff0c;具体包括查找头文件、进行宏替换、根据条件编译等操作。 g -E example.cpp -…