问题是,如果某个通道关闭,则从该特定通道读取会导致nil, false
对。如果两个通道都关闭,那么您将永远不会遇到默认情况,因为您的选择将在两个失败的读取之间交替,从而导致无限循环。
如果注释掉fmt.Printf()
函数,则for循环会非常快,以至于(但不能保证!)您可以在收集足够的树项之后但在Walk()
函数关闭通道之前进入循环因此输入默认大小写并中断循环。我试图给出一个可能的执行命令的示例,该命令将在下面完成其运行。
\\ t1 - thread of Walk(tree1)
\\ t2 - thread of Walk(tree2)
\\ t3 - thread of the loop
t1 > c.send()
t2 > c.send()
t3 > handle c1
t3 > handle c2
t3 > default, break
t1 > c.close()
t2 > c.close()
但是,放回IO操作会大大降低for循环的速度,以至于在关闭两个通道之前将没有机会输入select语句,因此它陷入了无限循环。现在发生的事情是这样的:
t1 > c.send() t2 > c.send() t3 > handle c1 // long IO operation t1 > c.close() t3 > handle c2 // long IO operation t2 > c.close() t3 > handle c1 with error t3 > handle c1 with error t3 > handle c2 with error ...
您应该在select语句之外处理中断条件。
for i1 < 10 || i2 < 10 {
select {
case x, ok := <-c1:
if ok {
fmt.Printf("ch1->%v i= %v\n", x, i1)
tre1[i1] = x
i1++
}
case y, ok := <-c2:
if ok {
fmt.Printf("ch2->%v i= %v\n", y, i2)
tre2[i2] = y
i2++
}
}
}