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个问题很深刻,目前脑子不够用,之后再来理解】
作者:西伯尔
出处:http://www.cnblogs.com/sybil-hxl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。