見出し画像

[Go言語 入門] 複数のchannelを同時に実行する。(select文)

golangで作ってみたいものがあり、golangを学び始めたので学習したことを書いていくノート。

---------------------------------------------------

サイトマップはこちら

---------------------------------------------------

第19回 複数のchannelを同時に実行する。(select)


前回の学習で、Goroutineで値を渡すには channel を使うことを学んだ。

今回は channel が複数あり、同時に実行したい場合、どのようにすればいいか学ぶ。

複数の channel を同時に実行するには「select文」を使用する。

今回は、1秒ごとにint型の「100」を送信し続けるgoroutinInt関数と、1秒ごとに文字列型の「Hello World!」を送信し続けるgoroutinString関数を並列処理する。

※time.Sleepを使用している理由は出力をわかりやすくするため。

// main.go

// 数値を送信し続ける並列処理
func goroutinInt(ch chan int) {
	for {
		ch <- 100
		time.Sleep(1 * time.Second)
	}
}

// 文字列を送信し続ける並列処理
func goroutinString(ch chan string) {
	for {
		ch <- "Hello World!"
		time.Sleep(1 * time.Second)
	}
}

main関数は以下

func main() {
	chInt := make(chan int)
	chStr := make(chan string)

	go goroutinInt(chInt)
	go goroutinString(chStr)

	for {
		select {
		case i := <-chInt:
			fmt.Println(i)
		case s := <-chStr:
			fmt.Println(s)
		}
	}
}

// 実行結果
// 100
// Hello World!
// 100
// Hello World!
// Hello World!
// 100
// Hello World!
// 100
// Hello World!
//     :
//     : 

それぞれに channel を作成し、Goroutineへ渡している。

for文の無限ループ内にselect文を作り、caseで条件分岐すると並列処理の同時実行が可能となる。

・goroutinInt関数から「100」が送信されてきたら、変数 i で受信し出力。

・goroutinString関数から「Hello World!」が送信されてきたら、変数 s で受信し出力。


~ forループから抜け出す方法 ~

上記のプログラムに5秒後ごとにBool型の「true」を返すgoroutinBool関数を追加する。

// main2.go

// Boolを送信し続ける並列処理
func goroutinBool(ch chan bool) {
	for {
		ch <- true
		time.Sleep(5 * time.Second)
	}
}

goroutinBool関数から「true」を受信したらforループを抜け出したい。

この場合どのようにすればいいか。

ラベル付きbreak文を使う。

以下サンプル。

func main() {
	chInt := make(chan int)
	chStr := make(chan string)
	chBool := make(chan bool)

	go goroutinInt(chInt)
	go goroutinString(chStr)
	go goroutinBool(chBool)

LOOP:
	for {
		select {
		case i := <-chInt:
			fmt.Println(i)
		case s := <-chStr:
			fmt.Println(s)
		case b := <-chBool:
			fmt.Println(b)
			break LOOP
		}
	}
}

// 実行結果
// 100
// Hello World!
// 100
// Hello World!
// 100
// Hello World!
// 100
// Hello World!
// 100
// Hello World!
// true

「LOOP」という名前のラベルを作り、chBool が値を受信したらループから抜け出すために、case文を追加し、break文を設置。

ここでは「LOOP」と名付けたが、ラベル名に特に決まりはない。

break文は「break ラベル」と書く!

以上


いいなと思ったら応援しよう!