Golang(五)Context 的使用和源码分析
0. 前言
- golang 的 Context 包,是专门用来简化对于处理单次请求但是涉及到多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作,这些操作可能涉及多个 API 调用
- 常见场景如一个微服务后台,各个 RPC 接口逐个调用形成一个调用链,某一时刻超时,要通知调用链上所有正在调用的请求断开连接
- 这样的话, 我们就可以通过 Context,来跟踪这些 goroutine,并且通过 Context 来控制他们的目的,这就是 Golang 语言为我们提供的 Context,中文可以称之为”上下文“
1. 定义
- type Context interface {
- Deadline() (deadline time.Time, ok bool)
- Done() <-chan struct{}
- Err() error
- Value(key interface{}) interface{}
- }
- Context 的主要数据结构是一单向的继承关系的结构
- 根据使用场景的不同,每一层context都具备有一些不同的特性
- 这种层级式的组织也使得 context 易于扩展,职责清晰
- Deadline 方法是获取设置的截止时间的意思
- 第一个返回值为截止时间,即到了这个时间点,Context 会自动发起取消请求
- 第二个返回值为 false 时表示没有设置截止时间,如果需要取消的话,需要调用取消函数进行取消
- Done 方法返回一个只读的chan,类型为 struct{}
- 在 goroutine 中,如果该方法返回的chan可以读取,则意味着 parent context 已经发起了取消请求
- 我们通过 Done 方法收到这个信号后,就应该做清理操作,然后退出 goroutine,释放资源
- 之后,Err 方法会返回一个错误,告知为什么 Context 被取消
- Err 方法返回取消的错误原因,因为什么 Context 被取
- Value 方法获取该 Context 上绑定的值,是一个键值对,所以要通过一个 Key 才可以获取对应的值,这个值一般是线程安全的
2. 基本实现
- Golang 内置的 context 包,已经给出了 Context 的两个实现
- 一般在代码中,开始上下文的时候都是以这两个作为最顶层的 parent context 节点,然后再衍生出子 context
- 这些 Context 对象形成一棵树:当一个 Context 对象被取消时,它的所有子节点都会被取消。两个实现如下:
- type emptyCtx int
- func (*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
- }
- var (
- background = new(emptyCtx)
- todo = new(emptyCtx)
- )
- func Background() Context {
- return background
- }
- func TODO() Context {
- return todo
- }
- Background,主要用于 main 函数、初始化以及测试代码中,作为 Context 这个树结构的最顶层的 Context,但是不能被取消
- TODO,如果我们不知道该使用什么 Context 的时候,可以使用这个而不是传一个空接口
- 他们两个本质上都是 emptyCtx 结构体类型,是一个不可取消,没有设置截止时间,没有携带任何值的 Context
3. 继承和使用
- 通过 With 函数,可以创建 Context 树,树的每个节点都可以有任意多个子节点,节点层级可以有任意多个
- func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
- func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
- func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
- func WithValue(parent Context, key, val interface{}) Context
- WithCancel 函数,传递一个父 Context 作为参数,返回子 Context,以及一个取消函数用来取消 Context
- WithDeadline 函数,相对 WithCancel 多传递一个截止时间参数,意味着到了这个时间点,会自动取消 Context,也可以提前通过取消函数进行取消
- WithTimeout 和 WithDeadline 基本上一样,这个表示是超时自动取消,是多少时间后自动取消 Context 的意思
- WithValue 函数和取消 Context 无关,它是为了生成一个绑定了 key 、value 的数据的Context
- 这个绑定的数据可以通过 Context.Value 方法访问到,这是我们实际用经常要用到的技巧
- 一般我们想要通过上下文来传递数据时,可以通过这个方法
4. 参考文献
Golang(五)Context 的使用和源码分析的更多相关文章
- Golang的Context介绍及其源码分析
简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...
- Quartz学习--二 Hello Quartz! 和源码分析
Quartz学习--二 Hello Quartz! 和源码分析 三. Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...
- Android Debuggerd 简要介绍和源码分析(转载)
转载: http://dylangao.com/2014/05/16/android-debuggerd-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%92%8C%E ...
- Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析
相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...
- Kubernetes Job Controller 原理和源码分析(二)
概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...
- Kubernetes Job Controller 原理和源码分析(一)
概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...
- Kubernetes Job Controller 原理和源码分析(三)
概述Job controller 的启动processNextWorkItem()核心调谐逻辑入口 - syncJob()Pod 数量管理 - manageJob()小结 概述 源码版本:kubern ...
- jQuery静态方法globalEval使用和源码分析
Eval函数大家都很熟悉,但是globalEval方法却很少使用,大多数参考手册也没有相关api,下面就对其用法和源码相应介绍: jQuery.globalEval()函数用于全局性地执行一段Java ...
- Spring里的aop实现方式和源码分析
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点.业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点.横切关注点的一个特点是,他们经常发生在核心关 ...
随机推荐
- com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value异常
springboot对象返回,一直报生成json异常,经过检查,发现是自己在做xss防护时对出参进行了json的处理(copy代码不可取,囧) 异常信息 这里进行了出参处理了,但实际上只要对入参处理就 ...
- MSSQL 生成唯一自增数据的办法
我的应用场景是多进程并发获取这个计数,且要保证唯一且自增,我用的办法是锁表 计数表Counter,就一行数据 下面是存储过程 create procedure [dbo].[GetCount] AS ...
- .net core SIMD范例分析
单指令多数据流(SIMD)是CPU基本运算之外为了提高并行处理多条数据效率的技术,常用于多媒体处理如视频,3D模拟的计算.实现方式不同品牌的CPU各有自己的指令集,如SSE MMX 3DNOW等. C ...
- 我为什么学习Haskell
说起来,Haskell真是相当冷门而小众的一门语言.在我工作第一年的时候,我平时从网络的一些学习资料上时不时看到有人提到这门语言.那时候的认识就是除了我们平时用的“面向对象语言 (OOP: Objec ...
- Windows怎么安装配置Elasticsearch
进入Elasticsearch官网,点击Download,Elasticsearch默认端口9200 然后进入下图:有各种版本,我选择windows版本 下载之后,解压得到Elasticsearch文 ...
- 【转载】Gradle学习 第十章:网络应用快速入门
转载地址:http://ask.android-studio.org/?/article/8 This chapter is a work in progress.这一章是一项正在进行中的工作. Th ...
- 0x02 Python logging模块利用配置加载logger
目录 logging模块利用配置加载logger 方式一模板:logging.config.dictConfig(config_dict) logging模块利用配置加载logger logging. ...
- JAVA concurrent包下Semaphore、CountDownLatch等用法
CountDownLatch 跟join的区别 CountDownLatch用处跟join很像,但是CountDownLatch更加灵活,如果子线程有多个阶段a.b.c; 那么我们可以实现在a阶段完成 ...
- Linux(Centos7)安装Oracle11.2.0数据字典初始化,监听,网络,创建用户等部分配置
#创建数据字典和pl/sql包 @/u01/app/oracle/product/11.2.0/db_1/rdbms/admin/catalog.sql; @/u01/app/oracle/produ ...
- iview admin动态路由实现
参考 https://blog.csdn.net/weixin_41538490/article/details/93749942