Go言語のselect文
select は Go における制御構造の一つで、switch文に似ています。
select文はチャネル操作にのみ使用でき、各caseはチャネル操作(送信または受信)でなければなりません。
select文は指定されたすべてのチャネル上の操作を監視し、いずれかのチャネルが準備でき次第、対応するコードブロックを実行します。
複数のチャネルが準備できている場合、select文はランダムに1つのチャネルを選んで実行します。すべてのチャネルが準備できていない場合は、defaultブロックのコードを実行します。
構文
Goプログラミング言語におけるselect文の構文は次のとおりです。
select {
case <- channel1:
// 実行するコード
case value := <- channel2:
// 実行するコード
case channel3 <- value:
// 実行するコード
// caseは任意の数だけ定義できます
default:
// すべてのチャネルが準備できていない場合に実行するコード
}
以下にselect文の構文を示します。
- 各caseはチャネルでなければなりません
- すべてのchannel式が評価されます
- 送信されるすべての式が評価されます
- 任意のチャネルが実行可能であれば、それが実行され、他は無視されます。
- 複数のcaseが実行可能な場合、selectはランダムかつ公平に1つを選んで実行し、他は実行されません。
そうでない場合:- default句があれば、その文を実行します。
- default句がない場合、selectはいずれかのチャネルが実行可能になるまでブロックします。Goはchannelや値を再評価しません。
実例
select文の適用デモ:
実例
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
上記のコードの実行結果は次のとおりです。
received one received two
上記の例では、2つのチャネルc1とc2を作成しました。
select文は2つのチャネルのデータを待ちます。c1のデータを受信すると "received one" を出力し、c2のデータを受信すると "received two" を出力します。
次の例では、2つのチャネルを定義し、2つのコルーチン(Goroutine)を起動してこれらのチャネルからデータを取得します。main関数では、select文を使用してこれら2つのチャネルに対してノンブロッキングな選択を行い、両方のチャネルに利用可能なデータがない場合はdefault句の文を実行します。
次の例を実行すると、2つのチャネルからデータを取得し続け、両方のチャネルに利用可能なデータがない場合は "no message received" と出力します。
実例
package main
import "fmt"
func main() {
// 2つのチャネルを定義
ch1 := make(chan string)
ch2 := make(chan string)
// 2つのgoroutineを起動し、それぞれのチャネルからデータを取得
go func() {
for {
ch1 <- "from 1"
}
}()
go func() {
for {
ch2 <- "from 2"
}
}()
// select文を使用して2つのチャネルからノンブロッキングでデータを取得
for {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
default:
// 両方のチャネルに利用可能なデータがない場合は、ここにある文を実行
fmt.Println("no message received")
}
}
}
import "fmt"
func main() {
// 2つのチャネルを定義
ch1 := make(chan string)
ch2 := make(chan string)
// 2つのgoroutineを起動し、それぞれのチャネルからデータを取得
go func() {
for {
ch1 <- "from 1"
}
}()
go func() {
for {
ch2 <- "from 2"
}
}()
// select文を使用して2つのチャネルからノンブロッキングでデータを取得
for {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
default:
// 両方のチャネルに利用可能なデータがない場合は、ここにある文を実行
fmt.Println("no message received")
}
}
}
Go言語の条件文