作用
context 包的作用是在 goroutine
树中传递截止时间以及取消信号
context.go
context.go 在$GOROOT/src/context/文件中,该文件件包含了一个context的接口
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
四个实现类型emptyCtx
、cancelCtx
、timerCtx
、valueCtx
emptyCtx
type emptyCtx int
emptyCtx 就是一个int 类型,通过调用
contxt.Background() //初始化一个context
或者
contxt.TODO() //初始化一个context,不止
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
}
cancelCtx 通过WithCancel() 方法来创建,其中children 是存储子context的
timerCtx
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
通过以下两个方法来创建timerCtx
//指定截止日期,传入一个要取消的时间
func WithDeadline(parent Context, d time.Time)(Context, CancelFunc)
//指定超时时间,传入一个超时时间,内部也是由WithDeadline 实现的,通过
// time.Now().Add(timeout)实现
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
timerCtx 中包含了cancelCtx 结构体,所以可以传入一个cancelCtx 给timerctx,
valueCtx
type valueCtx struct {
Context
key, val interface{}
}
valueCtx 的作用是给context附带值。但是当传入的key 值类型和value 一样的,如下:
var keyA string = "one"
ctx:=context.Background()
ctx1,cancel1:=context.WithCancel(ctx)
ctxA:=context.WithValue(ctx1,key1,"value1")
var keyB string = "one"
ctxB:=context.WithValue(ctxA,keyB,"value2")
那么就会导致ctxB.Value(keyA) 获取值的时候会获取到 value2
这个值。因为
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key { //这里会比较key 如果相等直接就返回这个ctx的值,上面例子中ctxA 和ctxB 中存的是都是string 类型,值也一样,所以就返回了ctxB的值
return c.val
}
return c.Context.Value(key)
}