1 回答
TA贡献1765条经验 获得超5个赞
在for循环的每次迭代中,select都会执行涉及评估通道操作数的语句。
在每次迭代time.After()中将被调用并创建一个新频道!
如果持续时间大于0,则该通道尚未准备好接收,因此将执行默认情况。不会再次测试/检查该通道,下一次迭代会创建一个新的通道,该通道将再次未准备好接收,因此default再次选择案例 - 一如既往。
解决方案非常简单,但可以在此答案中看到:
func Sleep(sec int) {
<-time.After(time.Second* time.Duration(sec))
}
修复您的变体:
如果你想让你的变体工作,你必须只创建一个频道(使用time.After()),存储返回的频道值,并始终检查这个频道。如果通道“启动”(从它接收到一个值),你必须从你的函数返回,因为不会从它接收更多的值,所以你的循环将保持无休止!
func myOwnSleep(duration int) {
ch := time.After(time.Second * time.Duration(duration))
for {
select {
case <-ch:
fmt.Println("slept!")
return // MUST RETURN, else endless loop!
default:
fmt.Println("Waiting")
}
}
}
请注意,尽管在从通道接收到值之前,此函数不会“休息”,只会无情地执行代码 - 加载一个 CPU 内核。如果只有 1 个 CPU 内核可用runtime.GOMAXPROCS(),这甚至可能会给您带来麻烦(),其他 goroutine(包括将(或将)发送到通道上的值的 goroutine)可能会被阻塞并且永远不会执行。睡眠(例如time.Sleep(time.Millisecond))可以释放 CPU 内核,使其免于无休止的工作(并允许其他 goroutine 运行)。
- 1 回答
- 0 关注
- 183 浏览
添加回答
举报