golang context包解析

目录

功能概要

接口

root节点

功能节点

valueCtx

cancelCtx

timerCtx

参考资料


功能概要

1、在一次请求过程中,可以在多(线程)进程间实现截止时间,取消信号,全局参数等功能;

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

2、context是按照树型结构进行组织的。已经实现的context类型包括emptyCtx,cancelCtx,timerCtx,valueCtx。一旦上层context被取消(不管是调用cancel函数,还是截止时间到期),下层的context均会收到取消信号。至于业务系统在context收到取消信号后何时停止剩余任务的执行,完全取决于业务系统本身,二者是异步的关系。

考虑下面这种情况:假如主协程中有多个任务1, 2, …m,主协程对这些任务有超时控制;而其中任务1又有多个子任务1, 2, …n,任务1对这些子任务也有自己的超时控制,那么这些子任务既要感知主协程的取消信号,也需要感知任务1的取消信号。

Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled.

3、WithCancel函数会返回一个可以取消的对象cancelCtx;WithDeadline和WithTimeout函数会返回一个有截止时间的对象timerCtx。除此以外,还会返回一个回掉函数CancelFunc做取消使用。

The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived Context (the child) and a CancelFunc. Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers. Failing to call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are used on all control-flow paths.

4、Context是线程安全的

The same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines.

接口

type Context interface {
	Deadline() (deadline time.Time, ok bool). // 返回任务的截止时间(channel关闭),ok为false表示没有截止时间
	Done() <-chan struct{} // 返回channel,其表示context被关闭,包括两种情形(1、cancel函数被调用,2、截止时间到达)
	Err() error // channel关闭的原因(1、取消,2、截止时间)
	Value(key interface{}) interface{} // 每个context可以关联一组key,value
}

root节点

// An emptyCtx is never canceled, has no values, and has no deadline. 
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
}

功能节点

valueCtx

该节点的主要功能是允许携带一对key,value

// 节点定义
type valueCtx struct {
	Context
	key, val interface{}
}
// 生成节点
func WithValue(parent Context, key, val interface{}) Context {
	if key == nil {
		panic("nil key")
	}
	if !reflectlite.TypeOf(key).Comparable() {
		panic("key is not comparable")
	}
	return &valueCtx{parent, key, val}
}

cancelCtx

该节点提供了一个可取消的函数,供业务系统调用

// 节点定义
type cancelCtx struct {
	Context
	mu       sync.Mutex            // protects following fields
	done     chan struct{}         // created lazily, closed by first cancel call
	children map[canceler]struct{} // set to nil by the first cancel call
	err      error                 // set to non-nil by the first cancel call
}
// 取消函数接口
type CancelFunc func()
// 生成节点
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	propagateCancel(parent, &c) // 将本节点和父节点关联起来,这样一旦父节点取消,本节点也一并被取消
	return &c, func() { c.cancel(true, Canceled) }
}

timerCtx

该节点的主要功能是提供一个截止时间,一旦截止时间到期,context会自动被取消

// 节点定义
type timerCtx struct {
	cancelCtx
	timer *time.Timer // Under cancelCtx.mu.
	deadline time.Time
}
// 生成节点
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
	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 passed
		return 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) }
}

参考资料

https://zhuanlan.zhihu.com/p/110085652

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值