关闭频道

问题描述:

我正在学习频道如何在Go中工作,并且偶然发现了关闭频道的问题。这是的一个修改示例,它产生n-1个斐波纳契数并通过通道发送它们,使通道容量的最后“元素”未被使用。关闭频道

func fibonacci(n int, c chan int) { 
    x, y := 0, 1 
    for i := 0; i < n-1; i++ { 
     c <- x 
     x, y = y, x+y 

    } 
    // close(c) // It's commented out on purpose 
} 

func main() { 
    n := 10 
    c := make(chan int, n) 
    go fibonacci(n, c) 

    for i := 0; i < n; i++ { 
     _, ok := <-c 
     fmt.Println(ok) 
    } 
} 

的问题是,我得到:

fatal error: all goroutines are asleep - deadlock!

当我不关闭通道。究竟是什么导致了僵局?为什么当我不关闭它时,我无法从容量边界的频道接收?

+1

如果您期望关闭某个通道,则读取通道的习惯方式为:for v:=范围c {'因为您不需要检查确定 - 当通道关闭时,for循环将会退出。如果你不希望频道关闭,请使用'for {select {case v:= eduncan911

你写了ň值进入通道(从0到n-1),但试图从通道读取n + 1值(从0到n)。在没有明确关闭频道的情况下,main函数将永远等待最后一个值。

What exactly is causing the deadlock?

ñ迭代,运行fibonacci功能够程将退出。在这个goroutine退出之后,你程序中唯一剩下的goroutine是main goroutine,而这个goroutine正在等待一些数据被写入到c通道 - 而且因为没有其他goroutine可以将数据写入这个频道,它会永远等待。这正是错误信息试图告诉你的:“所有程序(”全部“只是”一个“,在这里)都睡着了”

_, ok := <- c调用main函数只会在c通道关闭后立即停止阻塞(因为从通道读取被阻塞,这需要从另一个goroutine完成)。当通道关闭时,main函数将读取通道中的剩余数据(当它是缓冲通道时)

对于在通道主要预期N个通信循环,但只生产N-1在FUNC斐波纳契

func fibonacci(n int, c chan int) { 
    x, y := 0, 1 
    for i := 0; i < n; i++ { //here 
     c <- x 
     x, y = y, x+y 

    } 
    // close(c) // It's commented out on purpose 
} 

应该工作 http://play.golang.org/p/zdRuy14f9x

+0

我知道,这也是为了让渠道容量的一个“元素”变成空的。 – syntagma

+0

但它造成了僵局。主要你永远等待n的信息,因为你不发送它。 – Uvelichitel