0. 前言

  • golang 的 Context 包,是专门用来简化对于处理单次请求但是涉及到多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作,这些操作可能涉及多个 API 调用
  • 常见场景如一个微服务后台,各个 RPC 接口逐个调用形成一个调用链,某一时刻超时,要通知调用链上所有正在调用的请求断开连接
  • 这样的话, 我们就可以通过 Context,来跟踪这些 goroutine,并且通过 Context 来控制他们的目的,这就是 Golang 语言为我们提供的 Context,中文可以称之为”上下文“

1. 定义

  1. type Context interface {
  2.  
  3. Deadline() (deadline time.Time, ok bool)
  4.  
  5. Done() <-chan struct{}
  6.  
  7. Err() error
  8.  
  9. Value(key interface{}) interface{}
  10.  
  11. }
  • 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 对象被取消时,它的所有子节点都会被取消。两个实现如下:
  1. type emptyCtx int
  2.  
  3. func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
  4. return
  5. }
  6.  
  7. func (*emptyCtx) Done() <-chan struct{} {
  8. return nil
  9. }
  10.  
  11. func (*emptyCtx) Err() error {
  12. return nil
  13. }
  14.  
  15. func (*emptyCtx) Value(key interface{}) interface{} {
  16. return nil
  17. }
  18.  
  19. var (
  20. background = new(emptyCtx)
  21. todo = new(emptyCtx)
  22. )
  23.  
  24. func Background() Context {
  25. return background
  26. }
  27.  
  28. func TODO() Context {
  29. return todo
  30. }
  • Background,主要用于 main 函数、初始化以及测试代码中,作为 Context 这个树结构的最顶层的 Context,但是不能被取消
  • TODO,如果我们不知道该使用什么 Context 的时候,可以使用这个而不是传一个空接口
  • 他们两个本质上都是 emptyCtx 结构体类型,是一个不可取消,没有设置截止时间,没有携带任何值的 Context

3. 继承和使用

  • 通过 With 函数,可以创建 Context 树,树的每个节点都可以有任意多个子节点,节点层级可以有任意多个
  1. func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
  2.  
  3. func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
  4.  
  5. func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
  6.  
  7. 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 的使用和源码分析的更多相关文章

  1. Golang的Context介绍及其源码分析

    简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...

  2. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...

  3. 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 ...

  4. Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...

  5. Kubernetes Job Controller 原理和源码分析(二)

    概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...

  6. Kubernetes Job Controller 原理和源码分析(一)

    概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...

  7. Kubernetes Job Controller 原理和源码分析(三)

    概述Job controller 的启动processNextWorkItem()核心调谐逻辑入口 - syncJob()Pod 数量管理 - manageJob()小结 概述 源码版本:kubern ...

  8. jQuery静态方法globalEval使用和源码分析

    Eval函数大家都很熟悉,但是globalEval方法却很少使用,大多数参考手册也没有相关api,下面就对其用法和源码相应介绍: jQuery.globalEval()函数用于全局性地执行一段Java ...

  9. Spring里的aop实现方式和源码分析

    使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点.业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点.横切关注点的一个特点是,他们经常发生在核心关 ...

随机推荐

  1. com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value异常

    springboot对象返回,一直报生成json异常,经过检查,发现是自己在做xss防护时对出参进行了json的处理(copy代码不可取,囧) 异常信息 这里进行了出参处理了,但实际上只要对入参处理就 ...

  2. MSSQL 生成唯一自增数据的办法

    我的应用场景是多进程并发获取这个计数,且要保证唯一且自增,我用的办法是锁表 计数表Counter,就一行数据 下面是存储过程 create procedure [dbo].[GetCount] AS ...

  3. .net core SIMD范例分析

    单指令多数据流(SIMD)是CPU基本运算之外为了提高并行处理多条数据效率的技术,常用于多媒体处理如视频,3D模拟的计算.实现方式不同品牌的CPU各有自己的指令集,如SSE MMX 3DNOW等. C ...

  4. 我为什么学习Haskell

    说起来,Haskell真是相当冷门而小众的一门语言.在我工作第一年的时候,我平时从网络的一些学习资料上时不时看到有人提到这门语言.那时候的认识就是除了我们平时用的“面向对象语言 (OOP: Objec ...

  5. Windows怎么安装配置Elasticsearch

    进入Elasticsearch官网,点击Download,Elasticsearch默认端口9200 然后进入下图:有各种版本,我选择windows版本 下载之后,解压得到Elasticsearch文 ...

  6. 【转载】Gradle学习 第十章:网络应用快速入门

    转载地址:http://ask.android-studio.org/?/article/8 This chapter is a work in progress.这一章是一项正在进行中的工作. Th ...

  7. 0x02 Python logging模块利用配置加载logger

    目录 logging模块利用配置加载logger 方式一模板:logging.config.dictConfig(config_dict) logging模块利用配置加载logger logging. ...

  8. JAVA concurrent包下Semaphore、CountDownLatch等用法

    CountDownLatch 跟join的区别 CountDownLatch用处跟join很像,但是CountDownLatch更加灵活,如果子线程有多个阶段a.b.c; 那么我们可以实现在a阶段完成 ...

  9. Linux(Centos7)安装Oracle11.2.0数据字典初始化,监听,网络,创建用户等部分配置

    #创建数据字典和pl/sql包 @/u01/app/oracle/product/11.2.0/db_1/rdbms/admin/catalog.sql; @/u01/app/oracle/produ ...

  10. iview admin动态路由实现

    参考 https://blog.csdn.net/weixin_41538490/article/details/93749942