Go的context
context.Context
context.Context
一般用于并发控制。context
是一个接口包含四个方法。
type context interface {
Deadline() (deadline time.time, ok bool)
Done() <- struct{}
Err() error
Value(key any) any
}
Deadline的第一个返回值表示还有多久就到期,第二个返回值表示是否到期。
Done方法是使用的最频繁的一个方法,它返回一个chan。通常的做法是监听这个chan,如果收到信号则表示chan已经关闭,需要执行退出,如果chan已经关闭,则Err()返回退出的原因。
Value()方法返回指定的key对应的value,这是通过context携带的值,一般用在跨程序的API中,值的作用域在结束时停止。key必须是访问安全的,因为可能涉及到多个goroutine同时访问。一般常见的策略是在
context
中存储授权相关的值。主要用于安全凭证,分布式ID追踪,操作优先级,退出信息号以及到期时间等场景。
context常见的具体实现
context
是一个接口,这就需要具体的实现。context.Background
函数一般用作于根对象的存在,不可以退出,不可以携带值。
需要具体的使用context
的功能,就需要派生出新的context
。
用于退出的函数:
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithTimeOut(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
func WithValue(parent Context, key, val any) Context
WithCancel
函数返回一个子context
并且包含cancel
退出方法。子context
在两种情况下会退出:一种是调用
cancel
;另一种是当参数中父
context
退出时,该context
及其衍生的子context
都会全部退出。WithTimeout
函数指定一个超时时间,当超时发生时,子context
将会退出。因此子context
退出有三种情况:父
context
退出超时退出
主动调用
cancel
函数退出WithDeadline
函数与WithTimeOut
类似,前者指定的截止日期,后者指定的时间段。WithValue
函数返回带key-value
的子context
。
Context的原理
context
在很大程度上利用了chan在close时会通知所有监听的它的goroutine这个特性实现的。