课程名称:GO开发工程师
课程章节:6-8:并发任务非控制
课程讲师: ccmouse
课程内容:
- 非阻塞等待代码示例
func nonBlockingWait(c chan string) (string, bool) {
select {
case m := <-c:
return m, true
default: // 加了default就实现了非阻塞式等待
return "", false
}
}
- 等待超时代码示例
func timeOutWait(c chan string, timeout time.Duration) (string, bool) {
select {
case m := <-c:
return m, true
case <-time.After(timeout):
return "", false
}
}
- 优雅退出:
// chan bool / chan struct{} 都可以, chan struct{}更省空间
func msgGenDone(name string, done chan struct{}) chan string {
c := make(chan string)
go func() {
i := 0
for {
select {
case <-time.After(time.Duration(rand.Intn(5000)) * time.Second):
c <- fmt.Sprintf("message: %s--->%d", name, i)
case <-done: // 收到调用方退出的消息,开始执行清理工作
fmt.Println("clean start")
time.Sleep(2 * time.Second)
fmt.Println("clean done")
done <- struct{}{} // 清理完成后通知调用方
return
}
i++
}
}()
return c
}
课程收获:
-
问题: 关于time.After()
每一次执行select的时, time.After()都会产生一个Time chan去等待。
就算本次select结束以后,没有超时,这个Time chan 占用的空间会在各自的时间到期前越积越多吧。
解答:
Timer只有在时间到达才会被垃圾回收收回。如果需要更好的效率,建议采用NewTimer,然后在不需要的时候调用Timer.Stop -
问题:在一个goruntine发生异常后,通知其它goruntine结束
解答:
go语言没有“异常”的说法,只有error和panic。error的话,和我视频里的逻辑一样,通过done channel通知其他goroutine。
panic的话,可以参考之前的有关defer/panic/recover章节,recover了以后再通过done channel通知。
当然,我们通知的数据可以考虑包括done的原因,比如说是超时还是出错等。
热门评论
兄弟,看到回复一下