golang源码解读之context包

本文详细解读了Golang的context包,包括Context接口、Done()方法、Value()方法、deadlineExceededError对象、emptyCtx、canceler接口、cancelCtx和timerCtx结构体。还介绍了Context的主要创建方法,如Background、WithCancel、WithDeadline和WithValue,以及Context的使用规则和示例。
摘要由CSDN通过智能技术生成

Context上下文简介
当 一个请求被取消或者发生超时时,为了防止资源泄露,这个请求上 的所有goroutine 都应该被退出来。通过context传入,可以 将一些取消信息或者超时信息传递给其他协。
context 相当于 简洁得管理了goroutines的生命周期,context包定义了 不同上下文类型,它跨API边界和进程之间传递截止日期、取消信号和其他请求范围的值。

Context源码解读
1、Context接口

type Context interface {
   
	Deadline() (deadline time.Time, ok bool)
	// Deadline()方法 返回当前上下文的截至时间,即该上下文应该被取消的时间
	// 如果没有设置超时时间,则返回的ok为false

	// Done() 方法方法,当struct通道,有写出时实现
	Done() <-chan struct{
   }
	// 当代表此上下文完成的工作应取消时,Done返回一个被关闭的通道,如果无法取消此上下文,则Done可能返回nil
	//cancel函数返回后,Done通道的关闭可能会异步进行。
	//WithCancel安排在调用cancel时关闭Done;
	//WithDeadline安排在期限届满时关闭;
	//WithTimeout安排在超时结束时关闭Done。
	
	// Err()方法,代表被关闭的原因 
	Err() error
	// 如果Done尚未关闭,Err返回nil。 如果关闭了Done,Err将返回一个非nil错误,解释原因:如果上下文被取消,则是取消错误;如果上下文的截止日期已过,则超出截止时间错误。

	// Value()方法,返回与 key 相关了的值,不存在返回 nil
	Value(key interface{
   }) interface{
   }
	// 仅对传输进程和API边界的请求范围的数据使用上下文值,而不是为了给函数传递可选参数。
	// key标识上下文中的特定值,希望在上下文中存储值的函数通常在全局变量中分配一个key,然后将该key用作argument传给context.WithValue and Context.Value

Done()方法 在上下文被取消或超时时会关闭当前监听的通道,表示上下文不再监听,因此关闭可以 作为广播通知,告诉context相关的函数要停止当前工作然后退出。

创建Context时会返回CancelFunc函数,调用CancelFunc函数以及到了超时时间,会关闭Done()方法监听的channel,所以Done()需要放到select中。 父Context取消时,其子Context也会被取消。但是子Context取消时,其父Context不会被取消

Done用于select语句:Stream()使用DoSomething()生成值,并将其发送到输出,直到DoSomething返回错误或ctx.Done关闭

// func Stream(ctx context.Context, out chan<- Value) error {
   
	for {
   
		v, err := DoSomething(ctx)
		if err != nil {
   
			return err
			}
		select {
   
			case <-ctx.Done():
			return ctx.Err()
			case out <- v:
		}
	}
}

Value()方法通过key获取该key在上下文中关联的值,如果该key没有关联的值,则返回nil,多次调用同一个key,返回的结果是一样的

	var userKey key
	// NewContext返回一个携带值u的新上下文。
	func NewContext(ctx context.Context, u *User) context.Context {
   
		return context.WithValue(ctx, userKey, u)
	}

	// FromContext返回存储在上下文中的用户值(如果有)。
	func FromContext(ctx context.Context) (*User, bool) {
   
		u, ok := ctx.Value(userKey).(*User)
		return u, ok
	}

2、deadlineExceededError 对象

type deadlineExceededError struct{
   }

// (截止时间超时)对象 Error报错方法:返回字符串
func (deadlineExceededError) Error() string   {
    return "context deadline exceeded" }
// (截止时间超时)对象 Timeout超时方法:返回 是否超时
func (deadlineExceededError) Timeout() bool   {
    return true }
// (截止时间超时)对象 Temporary暂停方法:返回 是否暂停
func (deadlineExceededError) Temporary() bool {
    return true }

3、 emptyCtx对象
empty是空的Context,但是实现了Context的接口。emptyCtx没有超时时间,不能被取消,也不能存储任何额外信息,所以emptyCtx常用来作为Context的根节点

// 空上下文emptyCtx对象(int类型),以下实现了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
}

// 空上下文对象的String方法:如果空上下文对象是background、或者todo。。。,返回不同字符串
func (e *emptyCtx) String() string {
   
	switch e {
   
	case background:
		return "context.Background"
	case todo:
		return "context.TODO"
	}
	return "unknown empty Context"
}

由于emptyCtx是不能外部访问,所以我们只能用Background和TOD

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值