为了账号安全,请及时绑定邮箱和手机立即绑定

为什么即使我关闭频道后,我的“for-select”语句仍不断从频道接收信息?

为什么即使我关闭频道后,我的“for-select”语句仍不断从频道接收信息?

Go
30秒到达战场 2023-07-26 20:05:51
我有以下代码: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指定的通道。

另一个解决方案是:

函数可以从多个输入中读取数据,并通过将输入通道复用到单个通道上来继续执行,直到所有输入都关闭,该通道在所有输入都关闭时关闭。这称为扇入。

查看完整回答
反对 回复 2023-07-26
?
catspeake

TA贡献1111条经验 获得超0个赞

Go 编程语言规范

关闭

调用 close 后,并且接收到任何先前发送的值后,接收操作将返回通道类型的零值,而不会阻塞。

接收操作员

关闭通道上的接收操作始终可以立即进行,在收到任何先前发送的值后生成元素类型的零值。


查看完整回答
反对 回复 2023-07-26
  • 2 回答
  • 0 关注
  • 132 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信