【第十三回Go言語学習備忘録】チャネルを利用して値を返す!

2月 12, 2022

どもです。エコバックが無駄にポールスミスのsaisaiです。


本日はチャネルについて学んだので学習内容をまとめたいと思います。今回の記事は前回記事でまとめたgoroutineを引き続き使用していく内容となりますので、よければこちらもご覧ください。


それではさっそくチャネルについてみていきましょう。

チャネルとは

早い話"並列処理におけるreturn"と認識すれば良さそうです。goroutine行っている並列処理ではreturnで返り値を返すことができません。そのため、チャネルを利用して値を返します。参考コードを作成しつつ、その仕組みをみていきましょう。まずはmain関数です。

func main() {
	c := make(chan string) //チャネルを作成して変数に代入
	go goroutine1("Red", c)
	go goroutine2("blue", c)
	x := <-c
	fmt.Println(x) //Red Sun
	y := <-c
	fmt.Println(y) //Blue Moon
}

まずはmake関数を利用してチャネルを作成し、変数cに代入します。チャネルの作成には型の指定も必要ですので忘れないようにしておきましょう。並列処理するそれぞれの関数には、通常の引数にチャネルも引数として加えます。そして並列処理した関数から返ってきたチャネルの値を変数(x,y)に代入して出力するといった流れになります。

次に並列処理する関数の方をみていきましょう。

func goroutine1(s string, c chan string) {
	v := fmt.Sprintf("%v Sun", s)
	c <- v
}

func goroutine2(s string, c chan string) {
	v := fmt.Sprintf("%v Moon", s)
	time.Sleep(100 * time.Millisecond)
	c <- v
}

並列処理する関数の引数にもチャネルを加えます。形式は

変数 chan 型

となります。関数の処理結果を変数vに代入し、変数"v"の値を代入したチャネル"c"をmain関数に返します。

x := <-c
y := <-c

上記の部分で変数x,yにチャネルで返ってきた値が代入されています。ちなみにこのチャネルを代入した変数"c"は他の関数からチャネルが返ってくるまでmain関数内で待機します。つまり、チャネルを使用する場合はsync.Waitなどで並列処理を終了するタイミングを調整したりする必要はないということです。

最終的なコマンドは以下の通りです。

package main

import (
	"fmt"
	"time"
)

func goroutine1(s string, c chan string) {
	v := fmt.Sprintf("%v Sun", s)
	c <- v
}

func goroutine2(s string, c chan string) {
	v := fmt.Sprintf("%v Moon", s)
	time.Sleep(100 * time.Millisecond)
	c <- v
}

func main() {
	c := make(chan string)
	go goroutine1("Red", c)
	go goroutine2("blue", c)
	x := <-c
	fmt.Println(x) //Red Sun
	y := <-c
	fmt.Println(y) //Blue Moon
}

Buffered Channels

チャネルには順次値が代入されますが、バッファを制限することで入る値の数を制限することもできます。例えば上記のコードの場合は、チャネルに特にバッファを設定していないので変数cにはいくらでも値を代入できます。しかし、以下のように指定した場合は代入できる値の数が制限されます。

c := make(chan string, 2)

上記の場合、チャネルには2つの値しか代入できません。チャネルに入っている値を出力するか、バッファを変更しない限り3つ目以降はエラーとなってしまいます。

ひとこと

今回はチャネルについて学習した内容をまとめてみました。


実際にコードに落とし込んで記事を執筆することでやっと少し理解できたかなと思います。正直、教材や技術記事などを読んだりしただけでは全く理解できないほど難易度は高く感じました…。


goroutineを使いこなすには必須となるのがチャネルですので、どんどん使用してさらに理解度を深めたいと思います。


ここまで読んでいただきありがとうございました!


-saisai-


↓本日のオススメ

Golang

Posted by CY