チャネルから値を読み取るさまざまな方法が異なる振る舞いになるのはなぜか不思議です。提供されたコード:チャネルを読み取るための違いの方法
mychan := make(chan int)
go func() {
i := 0
for {
mychan <- i
<-time.After(time.Second * 1)
i++
}
}()
ゴルーチンmychan
チャネルに無限整数のシーケンスを「ストリーム」。あなたはそのよう<-mychan
で直接読み込む場合は、このコードの後、:予想通り
fmt.Println(<-mychan)
これは、「0」を出力します。繰り返し続けている場合は、読み取りを続けます。
fmt.Println(<-mychan) // 1
fmt.Println(<-mychan) // 2
//...
ただし、ルーピングメカニズムを使用すると、無限にブロックされます。
for i := range mychan {
fmt.Println(i)
}
つまり、このメカニズムはクローズドチャネルからのみ読み取ることができます。 しかし、select
方法で、事はwierder取得します。
for i:=0; i<=10;i++ {
select {
case <-mychan:
fmt.Println(<-mychan)
}
}
は、今では同じように、交互に印刷さ1、3、5、9、... select
はmychan
や他のいくつかの不可視のチャンネルを切り替えたかのように、すべての2S。別のcase
(しゃれが意図していない)ケースを作るの追加:誰も私を説明し、啓発することができれば、あなたのいくつかに思えるそれはよいとして
for i:=0; i<=10;i++ {
select {
case <-time.After(1 * time.Second):
fmt.Println("foo")
case <-mychan:
fmt.Println(<-mychan)
}
}
// now prints 1, foo, 3, foo, 5, foo, ... every 1s
として、些細な質問を、私は感謝します。
注意してこの問題を解決することができます。それは私の1、3、5、...を参照してください。あなたは、ケースiのmyhcan:fmt.Println(i)を希望するかもしれません。 – Volker
すべてのチャンネルの受信操作は同じです。閉じたチャネルの状態を表示)。あなたが持っている動作の唯一の違いは、select文で受け取った値を1つおきに破棄することです。 – JimB
https://play.golang.org/p/CEMKqJF3ya < - このコードスニペットは、範囲キーワードがオープンチャンネルで動作することを「証明」しています。なぜ私のプログラムがハングアップするのかはかなり興味があります。それは何とか閉じられないことを知っていますか? –