1、利用channel关闭,实现Context.Done()

这个Context.Done()的具体实现,需要看源码:

func (c *cancelCtx) Done() <-chan struct{} {
	c.mu.Lock()
	if c.done == nil {
		c.done = make(chan struct{})
	}
	d := c.done
	c.mu.Unlock()
	return d
}

Done方法原理:当Context被取消或者到了deadline返回一个被关闭的channel
当contxt用完被销毁后,就会关掉这个返回的匿名chan struct{},这样Done()本身读这个channel就会返回err,即有返回值,也就满足了这个case。
当contxt未销毁时,这个匿名channel未关闭,是空的,就会阻塞,就不会进入这个case。

这里实现了Done方法,返回的是一个只读的channel,目的就是我们在外部可以通过这个阻塞的channel等待通知信号。
Done() 返回一个只读的channel;读一个关闭的channel可以读出对应类型的零值,而且也没有其他地方会向这个channel推入值,相当于就是实现了一个receive-only的channel。

func (c *Client) readPump(stopCtx context.Context) {
	...
	for {
		select {
		case <-stopCtx.Done():
			return
		default:
                ...
                }
        }  
}

type Context interface {
	Done() <-chan struct{}
        ...
}

参考:
https://juejin.cn/post/7026629488741974046#heading-8
https://zhuanlan.zhihu.com/p/439718947 【最后3个问题很深刻,目前脑子不够用,之后再来理解】

posted on 2023-04-20 15:22  西伯尔  阅读(24)  评论(0编辑  收藏  举报