在下面的代码中,迭代运行两次
是否有可能在第一次迭代和第二次迭代之间运行“test2< - true”?
我的意思是,当第一次迭代结束并且第二次迭代没有开始时,是否有变化发送到“test2”?
package main
import "log"
import "time"
func main() {
test := make(chan bool, 1)
test2 := make(chan bool, 1)
go func() {
for {
select {
case <-test:
log.Println("test")
case <-test2:
log.Println("test2")
}
}
}()
test <- true
time.Sleep(1)
test2 <- true
time.Sleep(1)
}
答案 0 :(得分:4)
是。由于您的频道已缓冲并且可以容纳1个值。主执行流程可以继续,而不会让您的匿名goroutine读取您发送到test
频道的值,并且它可以在goroutine唤醒之前在test2
频道上发送值并读取{上的值{1}}频道。
这种情况不太可能发生,因为你有一个time.Sleep()调用那里通常会给goroutine执行时间,但是没有人知道在你的机器非常繁忙的角落里会发生什么在(非)幸运时间暂停权力或其他你没想过的事情。
如果您的test
频道未缓冲,test
语句会阻止,直到您的goroutine收到该值,并且goroutine至少不可能从test <- true
收到从test2
频道收到任何内容。
答案 1 :(得分:3)
添加到nos&#39; answer,您可以模拟这种情况(其中&#34; test2 <- true
&#34;在第一次迭代和第二次迭代之间的时刻运行&#34;)通过制作很容易您的第一个留言接收(case <- test
)等一秒钟。
case <-test:
log.Println("test")
time.Sleep(1 * time.Second)
当匿名goroutine唤醒时,main()
已经将其两条消息发送到两个缓冲通道(缓冲区意味着非blokcing 一条消息),并退出。登记/>
如果main()
退出,其他所有内容,包括忙着睡觉的goroutine,都会停止。
参见 play.golang.org :输出为:
2009/11/10 23:00:00 test
您没有时间看test2
。
为了确保您的goroutine可以处理两个消息,您需要:
main()
等待所说的goroutine完成。这就是sync
package发挥作用的地方,使用(例如,这不是唯一的解决方案)WaitGroup
指令。
var wg sync.WaitGroup
wg.Add(1)
go func() {
// Decrement the counter when the goroutine completes.
defer wg.Done()
...
}
... // end of main():
// Wait for goroutine to complete.
wg.Wait()
goroutine在某个时间实际退出(而不是永远停留在for
循环中)。请参阅&#34; In Go, does a break statement break from a switch/select?&#34;
loop: <==========
for {
select {
case <-test:
log.Println("test")
time.Sleep(1 * time.Second)
case <-test2:
log.Println("test2")
break loop <==========
}
}
请参阅 play.golang.org :在test2
之后goroutine正在休眠时发送消息test1
,但main()
将等待({{1} }},并且goroutine将有机会在一秒钟之后阅读并打印wg.Wait()
。
输出结果为:
test2