本文へスキップ
BecomeCoder

Goコース · 第6章 並行処理 · レッスン24

select ― 複数のチャネルを待ち受ける

ブラウザで完結

導入

複数のチャネルのうち「先に届いたほう」を処理したいことがあります。そのための構文が 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 Playground や手元の環境で、実際に go run しながら手を動かしてみてください。

実際に動かしてみよう

下のエディタにGoを書いて「実行」を押すと、学習用シミュレータが fmt の出力を表示します(本物のGoコンパイラではなく、教材の範囲を再現した軽量エンジンです)。スライス・マップ・構造体・インターフェース・goroutine/channel なども動きます。本文の例を書き換えて動かしてみましょう(並行処理の実行順は決定的に再現しているため、本物のインターリーブとは異なる場合があります)。

Go — ブラウザ内で実行(学習用シミュレータ)

Goの教材サブセットを動かす学習用シミュレータを読み込みます(本物のGoコンパイラではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。