導入
複数のチャネルのうち「先に届いたほう」を処理したいことがあります。そのための構文が select です。並行処理版の switch と考えると分かりやすいでしょう。
説明
package main
import (
"fmt"
"time"
)
func main() {
fast := make(chan string)
slow := make(chan string)
go func() { time.Sleep(100 * time.Millisecond); fast <- "速い方" }()
go func() { time.Sleep(300 * time.Millisecond); slow <- "遅い方" }()
for i := 0; i < 2; i++ {
select {
case msg := <-fast:
fmt.Println("受信:", msg)
case msg := <-slow:
fmt.Println("受信:", msg)
}
}
}
select { case ... }… 複数のcase(それぞれチャネルの受信)のうち、準備ができたものが実行されます。- どれも準備できていなければ、いずれかが届くまで待ちます。
- タイムアウトを組み合わせるときは
case <-time.After(1 * time.Second):のように書きます。
select はネットワーク処理などで「応答が来たら処理、一定時間来なければ諦める」といったパターンに欠かせません。
やってみよう
上の例では、先に届く「速い方」が先に表示されます。time.Sleep の値を入れ替えると、表示の順番も入れ替わります。「準備できたチャネルから処理する」感覚をつかみましょう。
これで Go コースの入門は終わりです。基本文法から並行処理まで、ブラウザ内の実行環境で動かしながら Go の核となる考え方を一通りたどりました。次は手元に Go をインストールして(または Go Playground で)、自分で小さなプログラムを go run しながら手を広げてみてください。
演習
3つ目のチャネル mid(送る文字列は まん中)を足して、3回受信できるようにしてください。
ヒント1を見る
mid := make(chan string) を作り、送る goroutine を1つ増やし、select に case msg := <-mid: を足します。
ヒント2を見る
受信の回数も for i := 0; i < 3; i++ に変えます(この学習用シミュレータは実時間の待ち時間までは再現しないので、届く順番は本物の Go とは異なることがあります)。