我有以下代码:package mainimport ( "fmt" "time")func main() { ch := make(chan int) ch2 := make(chan int) go func(c chan int, c2 chan int) { for { select { case v := <-c: fmt.Println(v) case v := <-c2: fmt.Println(v) default: } } }(ch, ch2) ch <- 1 close(ch) close(ch2) time.Sleep(10 * time.Second)}当我运行它时,它会打印1到标准输出,然后继续打印0。为什么是这样?我知道我可以检查我的 goroutine 中的通道是否关闭,但我只想知道原因。另外,假设我想在所有(多个)通道关闭后退出 goroutine,这可能吗?我假设一旦所有通道都关闭,我可能会在默认情况下在所有通道关闭后退出 goroutine
2 回答
幕布斯7119047
TA贡献1794条经验 获得超8个赞
这是每个规范的预期行为:接收运算符:
关闭通道上的接收操作始终可以立即进行,在收到任何先前发送的值后生成元素类型的零值。
如果您想在从通道接收到所有值(在关闭之前在通道上发送的值)后终止循环,请使用该for ... range
构造,例如:
c := make(chan int) // Initialize some channel for v := range c { fmt.Println("Received:", v) }
如果您有多个通道并且希望从所有通道接收数据,则可以使用多个 goroutine,每个 goroutine 都有一个for range
指定的通道。
另一个解决方案是:
函数可以从多个输入中读取数据,并通过将输入通道复用到单个通道上来继续执行,直到所有输入都关闭,该通道在所有输入都关闭时关闭。这称为扇入。
catspeake
TA贡献1111条经验 获得超0个赞
Go 编程语言规范
关闭
调用 close 后,并且接收到任何先前发送的值后,接收操作将返回通道类型的零值,而不会阻塞。
接收操作员
关闭通道上的接收操作始终可以立即进行,在收到任何先前发送的值后生成元素类型的零值。
- 2 回答
- 0 关注
- 126 浏览
添加回答
举报
0/150
提交
取消