为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我从关闭的通道接收值?

为什么我从关闭的通道接收值?

Go
白衣染霜花 2021-09-27 10:53:16
我正在调查渠道行为,我对他们的行为感到很困惑。规范说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 mainimport "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在通道范围之前移动语句,它将永远关闭它。所以我想知道为什么它也不适用于“time.Sleep”技巧。到那个时候(5 秒)所有的 go 例程都应该已经完成并且通道关闭了,不是吗?
查看完整描述

1 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

Go 编程语言规范

关闭

对于通道 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


查看完整回答
反对 回复 2021-09-27
  • 1 回答
  • 0 关注
  • 197 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信