Context中的cancelCtx的难点大白话解析
前言
context,学习golang的同学应该都接触过这个。就一个context.go的简单文件涵盖了很多golang的知识点,从设计模式到线程安全都有涵盖,当然一切的根本就是接口Context,但是其精髓应该是cancelCtx(到目前为止,不确保官方继续实现新的context)
接下来,不会大面积铺开对context进行讲解,主要解析cancelCtx的几个知识点(因为其核心也就那几个,了解了cancelCtx,timerCtx很快就了解了的)。
肯定会结合源码来讲,当然也都是大白话。我会通过引入族群的一些设定来讲解context,当然不了解设定的也可以看作是爷爷、爸爸 、孩子。
因为设定的问题,会有些大白话。大家谨慎食用。
还是要建议先自行去了解下context,有个初步的认识,而本文只希望能为大家拨开迷雾,彻底通透。
Context家族
种族名:context
特征:啥也不是能力(emptyCtx)、断绝能力(cancelCtx) 、延时断绝能力(timerCtx)、存储标记能力(valueCtx);
始祖:background;
设定:
- 每个context个体只能拥有其中一种能力
- 每个个体都会传承其父辈,且不会忘记他的上一辈
emptyCtx
啥也不是能力。没啥能力,是始祖之能力,后代中也会出现啥也不会只能啃老的。后代这种人我们一般都叫他们todo。
cancelCtx
断绝能力。为保全父辈,保全整个族群。可以在必要时刻将自己及自己的子嗣全部与族群脱离关系。所以拥有这种cancelCtx的,其时刻会带着一个记着自己子嗣的小本本( children map[canceler]struct{} ),什么时候自己又添子添孙啦,他就会在这个本子上记下来。(子孙:好可怕)
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
}
timerCtx
延时断绝能力。这种能力的人只能是从cancelCtx中产出,所以其是cancel一脉的(难怪都那么烈性)也就是说,其父辈必须是timerCtx或者cancelCtx类型的。
当然与cancelCtx不同的是,这种会提前设定好自己牺牲的时间,包括子孙。(可能是怕自己中途反悔不想死吧)
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
valueCtx
存储标记能力。这个就是在这个族群中担任的是存储管理的能力。
cancelCtx初始化
众所周知,我们初始化cancelCtx用下面这个方法
//通过这个方法,context族群可以生产出拥有大无畏自我牺牲的精神的cancelCtx,
//返回值:生产出的自己,还有个CancelFunc方法,这个就是他把自我断绝的权利交了出来
//自己的存在是死是活一切由天(coder)决定,这里我们的CancelFunc方法会在下文细说
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)<