【问题标题】:Why do I receive values from a closed channel?为什么我会从封闭的渠道接收值?
【发布时间】:2015-05-29 23:04:03
【问题描述】:

我正在调查渠道的行为,但我对他们的行为感到很困惑。规范说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 语句移动到频道范围之前,它会永久关闭它。所以我想知道为什么它也不能使用“time.Sleep”技巧。到那时(5 秒)所有的 goroutine 应该已经完成​​并且通道关闭了,不是吗?

【问题讨论】:

  • 您直接引用回答您问题的文档?? “...... 并且在之后收到任何先前发送的值......”顺便说一句,我怀疑当你移动关闭时,goroutines恐慌写入关闭的通道。
  • @DaveC 问题实际上是当我测试它时我没有时间。睡眠所以基本上我只是从一个封闭的频道读取,因为 go 例程没有时间发送任何值。 play.golang.org/p/ssBAwu3oXi

标签: concurrency go


【解决方案1】:

The Go Programming Language Specification

Close

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2022-07-01
    • 2017-02-11
    相关资源
    最近更新 更多