go context 源码刨析(二)

Context

上下文context.Context 是用来设置截止时间、同步信号,传递请求相关值的结构体。

context.Context 定义了四个需要实现的方法:

  • Deadline: 返回 context.Context 被取消的时间。
  • Done: 返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消后关闭,多次调用 Done 方法会返回同一个 Channel。
  • Err: 返回 context.Context 结束的原因,它只会在 Done 方法对应的 Channel 关闭时返回非空的值。
    • 如果 context.Context 被取消,会返回 Canceled 错误。
      -如果 context.Context 超时,会返回 DeadlineExceeded 错误。
  • Value: 从 context.Context 中获取键对应的值,对于同一个上下文来说,多次调用 Value 并传入相同的 Key 会返回相同的结果,该方法可以用来传递请求特定的数据。
type Context interface {Deadline() (deadline time.Time, ok bool)Done() <-chan struct{}Err() errorValue(key any) any
}

过期信号

context.WithDeadlinecontext.WithTimeout能创建被取消的的计时器上下文context.timerCtxcontext.WithTimeout只是调用了context.WithDeadline

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {return WithDeadline(parent, time.Now().Add(timeout))
}
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {if parent == nil {panic("cannot create context from nil parent")}if cur, ok := parent.Deadline(); ok && cur.Before(d) {// The current deadline is already sooner than the new one.return WithCancel(parent)}c := &timerCtx{cancelCtx: newCancelCtx(parent),deadline:  d,}propagateCancel(parent, c)dur := time.Until(d)if dur <= 0 {c.cancel(true, DeadlineExceeded) // deadline has already passedreturn c, func() { c.cancel(false, Canceled) }}c.mu.Lock()defer c.mu.Unlock()if c.err == nil {c.timer = time.AfterFunc(dur, func() {c.cancel(true, DeadlineExceeded)})}return c, func() { c.cancel(true, Canceled) }
}

context.WithDeadline 在创建 context.timerCtx 的过程中判断了父上下文的截止日期与当前日期,并通过 time.AfterFunc 创建定时器,当时间超过了截止日期后会调用 context.timerCtx.cancel 同步取消信号。

context.timerCtx 内部不仅通过嵌入 context.cancelCtx 结构体继承了相关的变量和方法,还通过持有的定时器 timer 和截止时间 deadline 实现了定时取消的功能。

type timerCtx struct {cancelCtxtimer *time.Timer // Under cancelCtx.mu.deadline time.Time
}
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {return c.deadline, true
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {c.cancelCtx.cancel(false, err)if removeFromParent {// Remove this timerCtx from its parent cancelCtx's children.removeChild(c.cancelCtx.Context, c)}c.mu.Lock()if c.timer != nil {c.timer.Stop()c.timer = nil}c.mu.Unlock()
}

一般用 withTimeout比较多:

		ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)defer cancel()

传值方法

context.WithValue能从父上下文中创建一个子上下文,传值的子上下文使用context.valueCtx类型。

这个方法笔者没有在真实生产中用过,用的都是 grpc 的 metadata

func WithValue(parent Context, key, val any) Context {if parent == nil {panic("cannot create context from nil parent")}if key == nil {panic("nil key")}if !reflectlite.TypeOf(key).Comparable() {panic("key is not comparable")}return &valueCtx{parent, key, val}
}

key 必须是可比较的,并且不应该是string或者内部自带的类型。

摘自: https: //github.com/golang/lint/blob/0da02fd607244e7cc2c7dd759075c1ac3ebfa759/testdata/contextkeytypes.go
func _() {c := context.Background()context.WithValue(c, "foo", "bar")          // MATCH /should not use basic type( untyped|)? string as key in context.WithValue/context.WithValue(c, true, "bar")           // MATCH /should not use basic type( untyped|)? bool as key in context.WithValue/context.WithValue(c, 1, "bar")              // MATCH /should not use basic type( untyped|)? int as key in context.WithValue/context.WithValue(c, int8(1), "bar")        // MATCH /should not use basic type int8 as key in context.WithValue/context.WithValue(c, int16(1), "bar")       // MATCH /should not use basic type int16 as key in context.WithValue/context.WithValue(c, int32(1), "bar")       // MATCH /should not use basic type int32 as key in context.WithValue/context.WithValue(c, rune(1), "bar")        // MATCH /should not use basic type rune as key in context.WithValue/context.WithValue(c, int64(1), "bar")       // MATCH /should not use basic type int64 as key in context.WithValue/context.WithValue(c, uint(1), "bar")        // MATCH /should not use basic type uint as key in context.WithValue/context.WithValue(c, uint8(1), "bar")       // MATCH /should not use basic type uint8 as key in context.WithValue/context.WithValue(c, byte(1), "bar")        // MATCH /should not use basic type byte as key in context.WithValue/context.WithValue(c, uint16(1), "bar")      // MATCH /should not use basic type uint16 as key in context.WithValue/context.WithValue(c, uint32(1), "bar")      // MATCH /should not use basic type uint32 as key in context.WithValue/context.WithValue(c, uint64(1), "bar")      // MATCH /should not use basic type uint64 as key in context.WithValue/context.WithValue(c, uintptr(1), "bar")     // MATCH /should not use basic type uintptr as key in context.WithValue/context.WithValue(c, float32(1.0), "bar")   // MATCH /should not use basic type float32 as key in context.WithValue/context.WithValue(c, float64(1.0), "bar")   // MATCH /should not use basic type float64 as key in context.WithValue/context.WithValue(c, complex64(1i), "bar")  // MATCH /should not use basic type complex64 as key in context.WithValue/context.WithValue(c, complex128(1i), "bar") // MATCH /should not use basic type complex128 as key in context.WithValue/context.WithValue(c, ctxKey{}, "bar")       // okcontext.WithValue(c, &ctxKey{}, "bar")      // ok*/
}

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

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

相关文章

【高等数学】傅里叶级数

最近刷了会抖音&#xff0c;看到一个非常有趣的现象&#xff1a;傅里叶级数&#xff0c;今天挑了几个视频来供大家学习。 1.傅里叶级数概念 【小崔说数】傅里叶级数专题https://www.bilibili.com/video/BV1Uq4y1q7xk?t117.4 2.傅里叶级数动画 【谜之舒适】12分钟的傅立叶级…

【docker】Dockerfile制作基础镜像 python 底层镜像制作 | 打包所有的requirement依赖

一、Dockerfile思想 我们正常的对一个项目进行打包 docker image 通常是在CI工具编译时进行对依赖的安装&#xff0c;比如golang的go get、python的pip install、node的npm install 等等 好处&#xff1a;我们更新了依赖可以动态的再编译时进行一个对依赖的更新 坏处&#xf…

转速传感器频率信号整形方波输出隔离变送器 地线干扰抑制 200mV~10V/0-12V/0-24V转0-5v/0-12v/0-24v/集电极输出

特点 转速传感器信号直接输入&#xff0c;方波信号输出正弦波、锯齿波信号输入&#xff0c;方波信号输出200mV峰值微弱信号的放大与整形不改变原波形频率&#xff0c;响应速度快电源、信号&#xff1a;输入/输出 3000VDC三隔离辅助电源&#xff1a;5V、12V、15V或24V直流单电源…

利用单线程池实现多线程并发顺序消费消息

1 背景 在某些场景下&#xff0c;我们需要保证消费消息的顺序性&#xff0c;可能要使用单线程处理任务。 这个在消息数量较少时&#xff0c;还是一个可行的方案&#xff0c;但在大量的数据消息情况下&#xff0c;单线程就显得力不从心了&#xff0c;所以这时候需要引入多线程。…

在4面体空间内2点结构占比

有一个4面体状空间&#xff0c;由3层甲烷状分子堆积而成&#xff0c;单个甲烷4面体边长10. 内有30个点&#xff0c;在30个点中取2点&#xff0c;有30*29/2435种取法。这里要求两个点的距离必须为6.123 在435个结构中只有40个符合要求 序数 结构 序数 结构 3 1 282 3 7…

利用 MyFlash 实现 MySQL 数据闪回

Github https://github.com/Meituan-Dianping/MyFlash MyFlash 限制 仅支持 5.6 与 5.7binlog 格式必须为 row&#xff0c;且 binlog_row_imagefull只能回滚DML&#xff08;增、删、改&#xff09; MySQL 准备 注&#xff1a; 本章 MySQL 是采用 Docker 部署&#xff0c;容器…

如何进行海外网络加速?告别卡顿与访问慢的方法

你是否经常在打开海外网站浏览网页时遇到响应缓慢的问题&#xff1f;或者在进行国际网络会议时&#xff0c;由于网络延迟影响与客户的交流&#xff1f;亦或是由于网络问题&#xff0c;导致OA、ERP、云储存等应用频繁因为数据包丢失而中断下载&#xff1f;如果你经常遇到这些问题…

centos7 离线安装zip和unzip

解压的时候发现不能解压&#xff0c;报-bash: unzip: command not found 1、访问https://www.rpmfind.net/linux/rpm2html/search.php?queryzip&submitSearch…&systemcentos&arch#/ 2、输入zip和centos搜索&#xff0c;选择el7下载 3、输入unzip和centos搜索&am…

显卡nvidia的CUDA和cuDNN的安装

显卡版本&#xff0c;和nvidia下载的 CUDA版本和CUDNN的关系 1. 显卡版本 nvidia-smi 硬件环境&#xff1a;显卡版本 4090 NVIDIA-SMI-555.85 我的驱动是510.85.02&#xff0c;驱动附带cuda12.5 2. nvidia下载的cuda版本 nvcc -V 我下载的是cuda12.5 cuda在安装版本过程…

【WPF编程宝典】第10讲:简单动画

1.基本动画 这些基本动画都应用与C#代码动画是WPF模型的核心部分&#xff0c;让动画动起来不需要使用计时器以及事件处理代码&#xff0c;可使用声明的方式创建动画。WPF动画第一条规则&#xff0c;每个动画都依赖于一个依赖项属性。WPF动画第二条规则&#xff0c;属性的动态化…

【Java 如何创建线程】

创建线程的方式一&#xff1a;继承Thread类 步骤&#xff1a; 定义一个类继承Thread类覆盖Thread类中的run&#xff08;&#xff09;方法直接创建Thread类的子类对象创建线程调用start方法开启线程并调用线程的任务run方法执行。 如果线程的目的是为了开启一条执行路径去运行…

互联网技术基础-计算机人必看

目录 1.Internet的工作原理 1、Internet是一个分组交换系统 2、路由器是Internet实现互连的“标准件” 3、TCP/IP是Internet的核心协议 4、客户机/服务器的工作模式 2. IP地址 2.1 IP地址分类 2.2特殊IP地址 2.3路由器和IP编制原则 2.4子网的划分 2.5 IPV6 3.域名系…

【因果推断python】46_估计量2

目录 连续型干预变量案例 非线性处理效果 关键思想 连续型干预变量案例 目标转换方法的另一个明显缺点是它仅适用于离散或二元处理。这是你在因果推理文献中经常看到的东西。大多数研究都是针对二元干预案例进行的&#xff0c;但您找不到很多关于连续干预的研究。这让我很困…

Bytebase 对接本地部署的 llama3 开启ChatSQL功能

Bytebase 是为开发人员、测试、DBA和运维工程师构建的数据库 DevOps 领域的&#xff0c;类 GitLab/GitHub 平台。 这篇文章主要关注 Bytebase SQL 编辑器中的 AI 增强功能。使用此功能您可以使用自然语言在 Bytebase SQL 编辑器中查询数据库。同时还能给出针对查询的索引建议&…

RK3568技术笔记十四 Ubuntu创建共享文件夹

单击“虚拟机”&#xff0c;单击“设置”&#xff0c;如图所示&#xff1a; 单击“选项”&#xff0c;选择“总是启用&#xff08;E&#xff09;”&#xff0c;单击“添加”&#xff0c;如图所示&#xff1a; 单击“下一步”&#xff0c;如图所示&#xff1a; 单击“浏览”添加…

Ranger配置图片及json文件预览

文章目录 前言下载apt下载pip下载 配置使用json文件预览方法一 修改scope用cat预览方法二 安装jq预览配置ranger 图片文件预览方法一 使用img2txt预览方法二 使用fim预览配置ranger 总结 前言 本文主要讲解Ranger12如何配置json及图片的预览设置&#xff0c;如下是ranger的介绍…

Spring AI 整合openAI的chatGpt

Spring AI支持ChatGPT&#xff0c;这是OpenAI的AI语言模型。ChatGPT在激发人们对人工智能驱动文本生成的兴趣方面发挥了重要作用。 SpringAi与Spring Boot 的整合详见上一篇文章&#xff1a; Spring AI 介绍以及与 Spring Boot 项目整合 下面分四个部分来分别说明和演示&#…

简单分享github

一、官网 GitHub: Let’s build from here GitHub 二、注册 通过简单的注册步骤&#xff0c;你就可以拥有一个属于自己的GitHub账号。再简单注册完成之后会需要验证你所输入的邮箱才能正常使用你的GitHub。 三、设置自己的库 在注册完成之后&#xff0c;完成一些简单的设置之…

Zookeeper 集群节点实现通信原理(一)

Zookeeper 集群节点实现通信原理(一) 多节点部署完启动时,为了选举发送自己节点选举的信息,是如何实现通信的,实现原理 在 Zookeeper 的多节点集群中,为了选举领导节点,每个节点需要互相通信以发送和接收选举信息。 这种通信是通过一种称为 Fast Leader Election 的算法…

简单且高效的水域物探轨迹坐标转换程序

简单且高效的水域物探轨迹坐标转换程序 前言 水上测线的高精度定位是水域物探的难题&#xff0c;水域磁法、水域地震实施时常采用船舶拖拽传感器进行走航式观测&#xff0c;GPS仪器放在船舶上测量&#xff0c;造成船舶位置与传感器位置存在偏差&#xff0c;后期资料整理需要校…