go - 为什么通道阻塞时select语句会抛出错误
问题描述
在此示例中,通道已满,因此 select 语句中的第一个 case 将阻塞,从而导致打印 default case。或者至少那是我认为应该发生的事情。相反,我收到错误“所有 goroutines 都在睡觉 - 死锁!”。为什么是这样?我认为 select 语句会阻塞,直到其中一种情况可以运行,这是本示例中的默认情况。
func main() {
c := make(chan int)
c <- 1
select {
case c <- 5:
fmt.Println("a")
default:
fmt.Println("only case not blocked")
// fatal error: all goroutines are asleep - deadlock!
}
}
解决方案
通道是为 goroutine 通信而设计的。当一个通道已满时,发送者等待另一个 goroutine 接收它。
无缓冲的通道总是满的:必须有另一个 goroutine 来接收发送者发送的内容(同时)。
在这一部分中,您将写入一个频道:
c <- 1
这个也写入无缓冲通道,这会阻止它:
case c <- 5:
这个例子基于你的代码来展示它是如何工作的:
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go func() {
fmt.Println(<-c) // starting goroutine and continuously reading from chan "c"
}()
time.Sleep(time.Millisecond) //to let goroutine start before program ends
select {
case c <- 5: // write into the channel so goroutine can read
fmt.Println("a")
default:
fmt.Println("only case not blocked")
}
time.Sleep(time.Millisecond) //to let goroutine start before program finishes
}
推荐阅读
- selenium-firefoxdriver - RIDE 在运行屏幕测试时找不到 firefox geckodriver
- response - SteamedResponse 在其他服务器上的流明中不起作用
- postgresql - postgres的pgAdmin4登录问题
- python - 获取转换后逻辑回归最重要特征的名称
- mysql - 删除 Select Inner Join 查询结果
- apache-kafka - 仅在 Kafka Connect 中看到 1 个工作人员
- sequelize.js - SequelizeDatabaseError:无法打开引用的表“成员”
- google-apps-script - 通过脚本在相关下拉列表/数据验证中设置默认列表值
- react-native - 反应原生的可读流
- google-bigquery - 如何从一列中提取逗号分隔值并将它们分别放在 Google Data Studio 中的单独列中?