为什么我的 `for-select` 语句即使在我关闭它后仍继续从我的频道接收?
Why does my `for-select` statement keeps receiving from my channel even after I close it?
我有以下代码:
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
到stdout,然后继续打印0
。这是为什么?
我知道我可以在我的 goroutine 中检查通道是否关闭,但我只想知道关闭的原因。
此外,假设我想在所有(多个)通道关闭后退出 goroutine,这可能吗?我假设一旦所有通道都关闭,在默认情况下,我可能会在所有通道关闭后退出 goroutine
的预期行为
A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.
见
如果您想在从通道接收到所有值(在通道关闭之前发送到通道上)后终止循环,请使用 for ... range
结构,例如:
c := make(chan int) // Initialize some channel
for v := range c {
fmt.Println("Received:", v)
}
如果你有多个频道并且你想从所有频道接收,你可以使用多个 goroutines,每个 goroutines 都有一个 for range
用于指定的频道。
另一个解决方案是:
A function can read from multiple inputs and proceed until all are closed by multiplexing the input channels onto a single channel that's closed when all the inputs are closed. This is called fan-in.
The Go Programming Language Specification
After calling close, and after any previously sent values have been
received, receive operations will return the zero value for the
channel's type without blocking.
A receive operation on a closed channel can always proceed
immediately, yielding the element type's zero value after any
previously sent values have been received.
我有以下代码:
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
到stdout,然后继续打印0
。这是为什么?
我知道我可以在我的 goroutine 中检查通道是否关闭,但我只想知道关闭的原因。
此外,假设我想在所有(多个)通道关闭后退出 goroutine,这可能吗?我假设一旦所有通道都关闭,在默认情况下,我可能会在所有通道关闭后退出 goroutine
A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.
见
如果您想在从通道接收到所有值(在通道关闭之前发送到通道上)后终止循环,请使用 for ... range
结构,例如:
c := make(chan int) // Initialize some channel
for v := range c {
fmt.Println("Received:", v)
}
如果你有多个频道并且你想从所有频道接收,你可以使用多个 goroutines,每个 goroutines 都有一个 for range
用于指定的频道。
另一个解决方案是:
A function can read from multiple inputs and proceed until all are closed by multiplexing the input channels onto a single channel that's closed when all the inputs are closed. This is called fan-in.
The Go Programming Language Specification
After calling close, and after any previously sent values have been received, receive operations will return the zero value for the channel's type without blocking.
A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.