猿问

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

我有以下代码:


package main


import (

    "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


30秒到达战场
浏览 133回答 2
2回答

幕布斯7119047

这是每个规范的预期行为:接收运算符:关闭通道上的接收操作始终可以立即进行,在收到任何先前发送的值后生成元素类型的零值。如果您想在从通道接收到所有值(在关闭之前在通道上发送的值)后终止循环,请使用该for ... range构造,例如:c := make(chan int) // Initialize some channel for v := range c {     fmt.Println("Received:", v) }如果您有多个通道并且希望从所有通道接收数据,则可以使用多个 goroutine,每个 goroutine 都有一个for range指定的通道。另一个解决方案是:函数可以从多个输入中读取数据,并通过将输入通道复用到单个通道上来继续执行,直到所有输入都关闭,该通道在所有输入都关闭时关闭。这称为扇入。

catspeake

Go 编程语言规范关闭调用 close 后,并且接收到任何先前发送的值后,接收操作将返回通道类型的零值,而不会阻塞。接收操作员关闭通道上的接收操作始终可以立即进行,在收到任何先前发送的值后生成元素类型的零值。
随时随地看视频慕课网APP

相关分类

Go
我要回答