Go言語のselect文の使い方を完全ガイド!初心者でもわかる並行処理の条件分岐
生徒
「Go言語で複数の処理を同時に動かしたいときって、どうやって条件分けするんですか?」
先生
「Go言語では、select文を使えば、複数の処理を並行(同時)に実行しながら、条件分岐をすることができますよ。」
生徒
「それって難しそう…並行処理とかよくわかりません。」
先生
「大丈夫です!このあと、初心者にもわかりやすく丁寧に解説していきます。一緒に学んでいきましょう!」
1. Go言語のselect文とは?
select文は、Go言語の並行処理(ゴルーチン)で使われる特殊な条件分岐の書き方です。
Go言語では、goroutine(ゴルーチン)という機能を使って、複数の処理を同時に動かすことができます。
そして、それぞれの処理で通信をするために、channel(チャネル)を使います。
このチャネルに対して、「どのチャネルから先にデータが来たか」によって処理を分けるのがselect文なのです。
2. select文の基本構文
select文は、次のような形で書きます。
select {
case 受信1:
// チャネル1からデータを受け取ったときの処理
case 受信2:
// チャネル2からデータを受け取ったときの処理
default:
// どのチャネルからもデータが無いときの処理(省略可)
}
複数のcaseの中で、最初にデータが届いたチャネルの処理だけが実行されます。
3. 実際にselect文を使ったサンプルを見てみよう
実際に、2つのチャネルを使って、どちらか先にデータが来た方の処理をする例を見てみましょう。
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch1 <- "チャネル1からデータが届きました"
}()
go func() {
time.Sleep(1 * time.Second)
ch2 <- "チャネル2からデータが届きました"
}()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}
このコードでは、ch1とch2という2つのチャネルがあります。1秒後にch2から、2秒後にch1からデータが届きます。
select文は、先に届いたch2のデータを受け取って、その処理を実行します。
実行結果:
チャネル2からデータが届きました
4. default文で待たずに処理する
select文にはdefault節を使うこともできます。
これは、どのチャネルにもデータが来ていないときに、すぐに別の処理をさせたい場合に使います。
select {
case msg := <-ch1:
fmt.Println(msg)
default:
fmt.Println("まだデータが来ていません")
}
この例では、チャネルch1からデータが来ていなければ、すぐに"まだデータが来ていません"と表示されます。
5. select文を使うときのポイント
- 1つでもcaseのチャネルにデータがあれば、select文はすぐに動く
- すべてのチャネルにデータがない場合は、select文は待機状態になる
- default節があると、待たずにすぐに実行される
この仕組みを使えば、複数の並行処理の中から、「一番早く終わった処理」を優先して動かすことができるのです。
6. 実生活で例えるなら?
イメージしやすくするために、select文を「電話の呼び出し」に例えてみましょう。
あなたが2つの電話を持っていて、どちらかが先に鳴ったら、そちらに出る…というのがselectの動きです。
どちらも鳴らなければ待ち続けるし、「電話が鳴らなかったらとりあえずテレビを見る」と決めているなら、それがdefaultです。
7. select文はどんな場面で役立つの?
ネットワーク通信やタイマー処理、ユーザー入力の待ち受けなど、さまざまな処理を同時に扱う場面でselect文は大活躍します。
たとえば、「3秒以内にサーバーから返事がなければタイムアウトする」という処理も、selectを使えば簡単に書けるのです。