群辉做网站服务器,云南微网站制作,新建免费网站,解决wordpress注册作用#xff1a;用于在go协程中 传递上下文、超时、取消、传值
底层实现#xff1a;是由互斥锁、channel、map来实现的 互斥锁#xff1a;保护临界资源 channel: 用于信号通知#xff0c;比如ctx.Done() map: 保存父ctx下派生的所有子ctx, 父ctx关闭#xff0c;子ctx都关…作用用于在go协程中 传递上下文、超时、取消、传值
底层实现是由互斥锁、channel、map来实现的 互斥锁保护临界资源 channel: 用于信号通知比如ctx.Done() map: 保存父ctx下派生的所有子ctx, 父ctx关闭子ctx都关闭 实现的接口
type Context interface {Deadline() (deadline time.Time, ok bool)Done() -chan struct{}Err() errorValue(key interface{}) interface{}
}空ctx
type emptyCtx intfunc (*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
}cancel ctx
使用map保存所有子ctx确保父ctx cancel后子ctx也cancel
type cancelCtx struct {Contextmu sync.Mutex // protects following fieldsdone chan struct{} // created lazily, closed by first cancel callchildren map[canceler]struct{} // set to nil by the first cancel callerr error // set to non-nil by the first cancel call
}func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {if parent nil {panic(cannot create context from nil parent)}c : newCancelCtx(parent)propagateCancel(parent, c)return c, func() { c.cancel(true, Canceled) }
}// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {return cancelCtx{Context: parent}
}func propagateCancel(parent Context, child canceler) {fmt.Println(propagateCancel)done : parent.Done()if done nil {return // parent is never canceled}select {case -done:// parent is already canceledchild.cancel(false, parent.Err())returndefault:}if p, ok : parentCancelCtx(parent); ok {p.mu.Lock()if p.err ! nil {// parent has already been canceledchild.cancel(false, p.err)} else {if p.children nil {p.children make(map[canceler]struct{})}// 保存子ctxp.children[child] struct{}{}}p.mu.Unlock()} else {atomic.AddInt32(goroutines, 1)go func() {select {case -parent.Done():child.cancel(false, parent.Err())case -child.Done():}}()}
}func (c *cancelCtx) cancel(removeFromParent bool, err error) {if err nil {panic(context: internal error: missing cancel error)}c.mu.Lock()if c.err ! nil {c.mu.Unlock()return // already canceled}c.err errif c.done nil {c.done closedchan} else {close(c.done) // 关闭channel, 用于通知ctx.Done()}// 关闭所有子ctxfor child : range c.children {// NOTE: acquiring the childs lock while holding parents lock.child.cancel(false, err)}c.children nilc.mu.Unlock()if removeFromParent {removeChild(c.Context, c)}
}
timeout ctx
在cancelctx的基础上实现只是多了个定时器自动调用cancel
type timerCtx struct {cancelCtxtimer *time.Timer // Under cancelCtx.mu.deadline time.Time
}func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {if parent nil {panic(cannot create context from nil parent)}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 passedreturn 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) }
}value ctx
type valueCtx struct {Contextkey, val interface{}
}
func WithValue(parent Context, key, val interface{}) Context {if parent nil {panic(cannot create context from nil parent)}if key nil {panic(nil key)}// if !reflectlite.TypeOf(key).Comparable() {// panic(key is not comparable)//}return valueCtx{parent, key, val}
}
func (c *valueCtx) Value(key interface{}) interface{} {if c.key key {return c.val}return c.Context.Value(key)
}