为什么从未达到退货声明

时间:2015-01-16 06:59:44

标签: go

请查看以下代码段

package main

import (
    "fmt"
    "time"
)

func sender(ch chan string) {

    ch <- "Hello"
    ch <- "Foo"
    ch <- "and"
    ch <- "Boo"
    close(ch)
}

func main() {

    ch := make(chan string)

    go sender(ch)

    for {
        select {
        case value := <-ch:
            fmt.Println(value)
        case <-time.After(time.Second * 2):
            fmt.Println("Return")
            return
        }
    }
}

结果我得到了空白的输出和时间。之后永远不会到达。为什么呢?

我注意到,当我尝试从封闭通道接收值时,它将从类型中接收零值。为什么我仍然可以通过封闭渠道获得价值?

我也可以检查一下,

v, ok := <-ch

如果ok为false,则关闭通道。

1 个答案:

答案 0 :(得分:4)

在for循环的每次迭代中都会创建一个新的两秒计时器。封闭的频道随时可以接收。代码永远循环,因为在关闭的通道准备接收之前,新计时器的通道永远不会准备好接收。

解决问题的一种方法是将频道设置为nil:

    case value, ok := <-ch:
        if !ok {
            ch = nil
        } else {
            fmt.Println(value)
        }

在零通道上接收从未准备好。

playground example

如果您希望循环最多运行两秒钟,那么您应该在循环之外创建计时器:

    after := time.After(time.Second * 2)

并在循环中选择这一个计时器:

    case <-after:
        fmt.Println("Return")
        return

playground example(在操场上添加睡眠示例)

您可以将通道设置为nil并在循环外创建计时器。

playground example