为什么我从封闭的渠道接收价值?

The*_*hat 1 concurrency go

我正在调查频道的行为,他们的行为让我很困惑。规范说,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.但是,即使到那个时候通道关闭了,我似乎仍然能在range语句中得到这些值。这是为什么?

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")
}
Run Code Online (Sandbox Code Playgroud)

编辑:看来,如果我将close语句移动到通道范围之前,它将永久关闭它。因此,我想知道为什么它也不能与“ time.Sleep”技巧一起使用。到那时(5秒),所有执行例程都应该已经完成​​,并且通道已关闭,不是吗?

pet*_*rSO 6

Go编程语言规范

关

对于通道c,内置函数close(c)记录该通道将不再发送任何值。在调用close之后,并且在接收到任何先前发送的值之后,接收操作将返回通道类型的零值而不会阻塞。

在通道缓冲区中,有5个先前发送的值,后跟一个close。

例如,

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")
}
Run Code Online (Sandbox Code Playgroud)

输出:

previously sent values 5
0
1
2
3
4
the channel should be closed by now
done
Run Code Online (Sandbox Code Playgroud)