Goのチャンネルやルーティンをいじってみて、誰かが説明してくれることを望んでいた独特の振る舞いに出くわしました。
以下は、別のゴルーチンで実行されている「リスナー」(selectステートメント)にチャネルを介して文字列を送信することにより、stdoutにいくつかの文字列を出力することになっている短いプログラムです。
package main
import (
"fmt"
"time"
)
func main() {
a := make(chan string)
go func() {
for {
select {
case <-a:
fmt.Print(<-a)
}
}
}()
a <- "Hello1\n"
a <- "Hello2\n"
a <- "Hello3\n"
a <- "Hello4\n"
time.Sleep(time.Second)
}
使用する
go func() {
for s := range a {
fmt.Print(s)
}
}()
// or even simpler
go func() {
for {
fmt.Print(<-a)
}
}()
期待どおりに動作します。ただし、selectステートメントを使用して最上位のスニペットを実行すると、次の出力が生成されます。
Hello2
Hello4
つまり、他のすべてのステートメントのみが出力されます。これはどんな魔術ですか?