2016-04-17 4 views
0

私はチャンネルがGoでどのように動作するのかを学習しており、チャンネルを閉じる際に問題が発生しました。これは、の修正された例です。のn-1個のフィボナッチ数を生成してチャネルに送信し、チャネル容量の最後の「要素」は使用しないままにします。Goでチャンネルを閉じる

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!

私はチャネルを閉じていないとき。デッドロックの原因は何ですか?私がそれを閉じないと、容量の境界でチャンネルから受信できないのはなぜですか?チャンネル内の主な期待n個の通信におけるループのために

+1

FYI、チャンネルを閉じることを期待している場合、範囲を確認する必要はありませんので、チャンネルを閉じるとループが終了します。あなたがチャンネルを閉じることを期待していないなら、 'for {select {case v:= < - c:...} 'を使用してください。そうすれば、タイムアウト、トークンキャンセルの監視などの追加の 'case '条件を持つことができ、終了条件が検出されたときにforループを解除することができます。 – eduncan911

答えて

5

を動作するはずFUNCのフィボナッチで唯一のn-1生成(0からn-1)ですが、チャンネル(0からn)から値n + 1の値を読み取ろうとしています。明示的にチャンネルを閉じることなく、main関数はこの最後の値を永遠に待ちます。

What exactly is causing the deadlock?

N回の反復後、fibonacci機能を実行ゴルーチンが終了します。このゴルーチンが終了した後、あなたのプログラムに残っている唯一のゴルーチンはmainのゴルーチンで、このゴルーチンはcチャンネルに書き込まれるデータを待っています。チャンネル、それは永遠に待つでしょう。これはまさにエラーメッセージがあなたに伝えようとしているものです。"すべてのゴルーチン(ここでは"すべて "はここで" 1 "です)は眠っています"

main関数で_, ok := <- cコールのみcチャネルは(ブロッキングされたチャネルから読み取るように、これは別のゴルーチンから実行する必要がある)が閉鎖されるとすぐに遮断停止します。チャネルが閉じられると、main関数はチャネルから残りのデータを読み込みます(バッファされたチャネルの場合)

0

が、あなたは

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 
} 

はあなたがチャネルにN値を書いている http://play.golang.org/p/zdRuy14f9x

+0

私も知っている、それは目的のために、チャネルの容量の1つの「要素」を空にすることです。 – syntagma

+0

しかし、デッドロックが発生します。メインでは、あなたがそれを送らないので、あなたはnのメッセージをチャンネルで永遠に待つ。 – Uvelichitel

関連する問題