Go Context包之cancelCtx实现

阅读: 评论:0

Go Context包之cancelCtx实现

Go Context包之cancelCtx实现

涉及的两个重要基础知识点:

    1. 关闭的channel里面读取数据默认永远有个零值兜底

    2. select里面加上default就不会阻塞

其一:

package mainimport "fmt"func main() {ch:= make(chan int)close(ch)for {select {case v :=<-ch:fmt.Println("value",v)}}
}//结果(关闭的channel永远能读到值)
value 0
value 0
value 0
value 0
value 0
value 0
value 0
......

 其二:

package mainimport "fmt"func main() {ch:= make(chan  int)for{select {case v:=<-ch:fmt.Println("value:",v)default:  //不加default会阻塞报错:fatal error: all goroutines are asleep - deadlock!}}
}

cancelCtx实现:

package realizeimport "sync"//必备知识:
//从开启的channel读数据会阻塞,但从关闭的channel里面读取数据,依然可以接受到之前已经成功发送的数据;如果channel中已经没有数据的话将产生一个零值的数据,这个零值在关闭的channel里面是无限的,可以一直读到
//实现原理
//cancel的实现原理,根节点创建一个channel,在每个子gorountine中进行channel接收的select监控(注意此处需要有default,不然会造成阻塞系统报错),
//当关闭channel时,cancnel channel就会因为接收到默认零值而进入select,此时便可以进行关闭等操作。//1.定义信号源context
//2.传递信号源并在gorountine监控
//3.信号源关闭
//4.gorountine关闭
var closedchan = make(chan struct{})func init() {//开启一个关闭的channelclose(closedchan)
}
type Context struct {mu sync.Mutexdone chan struct{}//关闭信号
}func NewCancelContext() Context {return Context{}
}
//发送关闭信号
func (ctx *Context)Cancel(){ctx.mu.Lock()if ctx.done == nil{//cancel方法在done()方法之前执行,此时还没生成channel,故直接赋值一个关闭的channel(这里是cancelcontext的精髓)ctx.done = closedchan}else{//cancel方法在done()方法之后执行,已经在done方法里面生成了channel,只需关闭即可close(ctx.done)}ctx.mu.Unlock()
}
//返回channel,懒创建
func (ctx *Context)Done() <-chan struct{} {ctx.mu.Lock() //必须加锁,防止if ctx.done == nil{ctx.done = make(chan struct{})}ctx.mu.Unlock()return ctx.done
}

调用案例跟context包的cancelCtx调用一一致

package mainimport ("exercise/context/realize""fmt""sync""time"
)
var wg sync.WaitGroup
func main() {ctx := realize.NewCancelContext()wg.Add(1)go work(ctx)//time.Sleep(time.Second*2)ctx.Cancel()//直接调用可能会会出现panic: close of nil channel,所以cancle方法里面有特殊的处理开启一个关闭的channelwg.Wait()
}
func work(ctx realize.Context)  {LOOP:for{fmt.Println("worker")time.Sleep(time.Second*1)select {case <-ctx.Done():fmt.Println("退出work")break LOOPdefault: //必须要设置default,因为没有channel的输入,只有接收和关闭,不设置default会造成select阻塞死锁}}wg.Done()
}

 

本文发布于:2024-01-30 03:38:48,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170655713218963.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Context   cancelCtx
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23