我正在调查渠道行为,我对他们的行为感到很困惑。规范说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.
但是看起来我仍然得到范围语句中的值,即使那时通道已关闭。那是为什么?
package main
import "fmt"
import "sync"
import "time"
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
print("the channel should be closed by now\n")
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("done")
}
编辑:似乎如果我在频道范围之前移动close
语句,它会将其关闭。因此,我想知道为什么它没有使用&#34; time.Sleep&#34;诡计。到那时(5秒),所有的例程都应该已经完成并且频道关闭了,不是吗?
答案 0 :(得分:3)
The Go Programming Language Specification
对于通道c,内置函数close(c)不再记录 值将在频道上发送。 在调用close之后,以及之前发送的任何值之后 收到,接收操作将返回零值 频道的类型没有阻止。
在通道缓冲区中,有5个先前发送的值,然后是关闭。
例如,
package main
import (
"fmt"
"sync"
"time"
)
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
fmt.Println("previously sent values", len(iCh))
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("the channel should be closed by now\n")
print("done")
}
输出:
previously sent values 5
0
1
2
3
4
the channel should be closed by now
done