为什么可以从封闭的 Channel 接收值
在 Go 中,channel 提供了 goroutine 之间的通信机制。当通道关闭时,表示不再发送任何值。但是,这并不意味着通道缓冲区中的现有值会立即被丢弃。
规范规定,关闭通道后,在收到零值之前仍然可以接收任何先前发送的值。这是因为通道的缓冲区充当队列,存储关闭操作之前发送的值。
工作原理:
考虑以下代码:
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) for i := range iCh { fmt.Printf("%v\n", i) } }
输出:
0 1 2 3 4
即使通道在之后关闭5秒后,for循环仍然收到关闭操作之前发送的5个值。这是因为通道缓冲区会存储这些值直到它们被消耗。
只有在接收到所有先前发送的值后,for 循环才会返回零值,表示通道已关闭。
为什么“Time.Sleep”技巧失败:
“time.Sleep”技巧并不能阻止goroutine 在通道关闭之前继续向通道发送值。当 goroutine 休眠 5 秒时,它们可能会发送额外的值,这些值仍会被 for 循环缓冲和接收。
以上是为什么关闭的Go Channel还能收到值?的详细内容。更多信息请关注PHP中文网其他相关文章!