go - 奇怪的选择案例默认行为
问题描述
有人可以解释我奇怪的选择案例默认行为吗?如果我将 fmt.printf(something %v\n) 放在案例中,它永远不会达到默认阶段并超时。但如果我推迟或评论 printf 没关系。截图:错误代码 被延迟评论 ,我在操场上的代码https://play.golang.org/p/FYsToHUJE43
解决方案
您的代码包含潜在的死锁,如果您的非默认情况足够慢(例如,在 IO 操作的情况下),它最终会发生。
问题是,如果一个通道关闭,那么从该特定通道读取会产生一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
...
您应该在您的选择语句之外处理您的中断条件。
推荐阅读
- python - 如何仅将推文的文本获取到 json 文件中
- java - 为什么 ThumbnailUtils.createVideoThumbnail() 从图库中获取视频时返回 null
- rust - 了解生命周期:借来的价值还不够活
- php - PHP - 如果没有 FETCH_ASSOC 值,则返回 NULL?
- python - 如何从 c# 运行 python spaCy 脚本?
- python - 无法在 Python 中打开 NPY 文件
- aws-cdk - AWS CDK 高级构造与低级构造之间的区别
- r - 将数据框拆分为单独的并应用公式来计算 R 中段的转换
- google-oauth - 如何正确地将谷歌登录代码放入 nuxt 组件中
- java - 没有外键的 JPA OneToOne 关联不起作用