Go言語のチャネル(channel)について見ていこうと思います。
並行処理としてゴルーチンを扱いましたが、別々の処理が行われているだけで、データの受け渡しがなされているわけではありません。
それを可能にするのがチャネルということになります。
チャネルの作成
チャネルを作成にはmake()を使います。チャネルには値を渡すことができ、その値をチャネルから取り出すことができます。
次のような形で利用します。
// チャネルの作成
c := make(chan 型名)
// チャネルに値を渡す
c <- [値]
// チャネルの値を取り出す
変数 <-c
まず、簡単なコードでチャネルの動きを確認してみましょう。
次のコードで見てみます。
package main
import "fmt"
func main() {
c := make(chan int)
go func() {
c <- 100
}()
x := <-c
fmt.Println(x)
}
main()関数の中で処理をしています。
make()を使ってint型のチャネルを作成しています。変数をcとしています。
無名関数を作って、goを使ってゴルーチンの処理を実行しています。関数の中でチャネルに100の値を渡しています。(c <- 100)
チャネルに渡した値を取り出して変数xに代入しています。(x := <-c)
最後に出力しています。
実行すると次のように出力されます。
100
チャネルに渡した値を受け渡しできているのが確認できます。
もうちょっと具体的な処理のコードで書いてみましょう。
package main
import "fmt"
func operation(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum
}
func main() {
s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
c := make(chan int)
go operation(s, c)
x := <-c
fmt.Println(x)
}
operation()という関数を定義しています。スライスとチャネルを引数にとって、スライスの値をfor文でのループ処理で取り出して順に加えて合計を求める処理をしています。その値をチャネルに渡しています。
main()の中で、変数sでint型のスライスを宣言して、1から10の値を持たせています。
makeでチャネルを設定し、ゴルーチンでoperation()を実行しています。引数にスライスとチャネルを渡しています。
ゴルーチンで処理して得た値をxに渡して、Println()で出力しています。
次のように出力されます。
55
main関数にoperation()で処理した値が受け渡しされているのがわかります。
チャネルと複数のゴルーチン
今度は上のコードを修正して、作成したチャネルに複数のゴルーチンを処理させてみます。
次のようなコードにしてみました。
package main
import "fmt"
func operation1(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum
}
func operation2(s []int, c chan int) {
sum := 100
for _, v := range s {
sum *= v
}
c <- sum
}
func main() {
s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
c := make(chan int)
go operation1(s, c)
go operation2(s, c)
x := <-c
fmt.Println(x)
y := <-c
fmt.Println(y)
}
ここでは、operation1()、operation2()の計算処理の違う二つの処理を定義してみました。
main()関数の中のスライスとチャネルはこれまでと同じですが、operation1()、operation2()の2つの処理をゴルーチンで行っています。
チャネルに渡された値を、x、yで受け取って出力する処理をしています。
実行するとこうなります。
362880000
55
このように、チャネルに処理されたものから値が渡されて、それが取り出されて出力されているのがわかります。
このようにチャンネル1つでもこのように処理ができます。別のチャンネルを作ってそれぞれ処理させるということもできます。
また、ここでは2つの関数を定義したが、同じ関数を複数回ゴルーチンで処理するということもできます。
最後に
Go言語のチャネルについて扱いました。
チャネルは並行処理の中で、値を受け渡しすることができるものです。
チャネルはmake(chan 型名)で作成し、「c <- 値」を使って値を渡し、「変数 <-c」を使って値を取り出します。
1つのチャネルでゴルーチンの処理を複数行うこともできますし、2つのチャネルで別々に行うこともできます。