暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Go语言之context

欢乐毅城 2021-07-27
208

注:每天进步一点点,记录每日成长,思考的第07/365天 ;  

本文预计阅读时间: 3分钟


1


01


context是什么

通过context,我们可以方便地对同一个请求所产生地goroutine进行约束管理,可以设定超时、deadline,甚至是取消这个请求相关的所有goroutine。


context包的核心

type Context interface {  
    //如果存在,返回当前Context任务被取消的截止时间;
    Deadline() (deadline time.Time, ok bool)
    
    //当Context被canceled或是times out的时候,Done返回一个被closed的channel;否则返回nil     
    //【用来传递结束信号以抢占并中断当前任务】
    Done() <-chan struct{}        

    //如果Done返回的channel没有关闭,将返回nil;
    //如果Done返回的channel已经关闭,将返回非空的值表示任务结束的原因。
    //如果是context被取消,Err将返回Canceled;
    //如果是context超时,Err将返回DeadlineExceeded。   
    Err() error 

    //如果存在,Value返回与key相关了的值,不存在返回 nil  
    Value(key interface{}) interface{}
}

复制


1


02


emptyCtx类型

emptyCtx
是一个int
类型的变量,它实现了context
的接口。emptyCtx
没有超时时间,不能取消,也不能存储任何额外信息,所以emptyCtx
用来作为context
树的根节点。

// emptyCtx不能被取消,没有值,也没有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
}

func (e *emptyCtx) String() string {
 switch e {
 case background:
  return "context.Background"
 case todo:
  return "context.TODO"
 }
 return "unknown empty Context"
}

var (
 background = new(emptyCtx)
 todo       = new(emptyCtx)
)

func Background() Context {
 return background
}

func TODO() Context {
 return todo
}

复制


有两种方法创建根 Context,一个是 Background(),一个是 TODO(),这两个函数都会返回一个空  Context 的实例。根 context 不会被 cancel。这两个方法只能用在最外层代码中,比如 main 函数里。一般使用 Background() 方法创建根 context。TODO() 用于当前不确定使用何种 context。


1


03


派生Context

一个Context被cannel,那么它的派生context 都会收到取消信号。有四种方法派生 context :

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

func WithValue(parent Context, key, val interface{}) Context

复制


WithCancel 对应的是 cancelCtx ,其中,返回一个 cancelCtx ,同时返回一个 CancelFunc,CancelFunc 是 context 包中定义的一个函数类型:type CancelFunc func()。调用这个 CancelFunc 时,关闭对应的c.done,也就是让他的后代goroutine退出。


WithDeadlineWithTimeout 对应的是 timerCtx ,WithDeadline 和 WithTimeout 是相似的,WithDeadline 是设置具体的 deadline 时间,到达 deadline 的时候,后代 goroutine 退出,而 WithTimeout 简单粗暴,直接 return WithDeadline(parent, time.Now().Add(timeout))。


WithValue 对应 valueCtx ,WithValue 是在 Context 中设置一个 map,拿到这个 Context 以及它的后代的 goroutine 都可以拿到 map 里的值。


1


04


Context使用规则

a)勿将Context作为struct的字段使用,而是对每个使用其的函数分别作参数使用,其需定义为函数或方法的第一个参数,一般叫作ctx;

b)勿对Context参数传nil,未想好的使用那个Context,请传context.TODO

c)使用context传值仅可用作请求域的数据,其它类型数据请不要滥用;

d)同一个Context可以传给使用其的多个goroutine,且Context可被多个goroutine同时安全访问。

1


05


总结

context
主要用于父子任务之间的同步取消信号,本质上是一种协程调度的方式。

文章转载自欢乐毅城,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论