首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Golang(五)Context 的使用和源码分析

Golang(五)Context 的使用和源码分析

作者头像
西凉风雷
发布2022-11-23 19:28:07
发布2022-11-23 19:28:07
3150
举报

0. 前言

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

1. 定义

代码语言:javascript
复制
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 对象被取消时,它的所有子节点都会被取消。两个实现如下:
代码语言:javascript
复制
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 树,树的每个节点都可以有任意多个子节点,节点层级可以有任意多个
代码语言:javascript
复制
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. 参考文献

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 前言
  • 1. 定义
  • 2. 基本实现
  • 3. 继承和使用
  • 4. 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档