今日はGoのProducerとConsumerというものについて学習したのでそれについてアウトプットしていきます。
前提知識
- Goの基礎文法
- チャネル
- Goroutine
このあたりの知識があると今回の記事は理解しやすいと思います。
分からない方はチャネルとGoroutineについては僕の方でも記事を書いているので良ければ参考にしてください!
【Golang】Go言語 channel(チャネル)について
【Golang】Go言語基礎 Goroutineとは?
Producer、Consumerとは?
func mainから走らせた並行処理(Producer)での処理結果をチャネルに送信し、送られてきた値をConsumerで処理していくといった流れです。
具体的に言うと、色々なサーバーへいってログを解析してきて結果をチャネルで送信し(Producer)、送られてきたチャネルの値をConsumerで受信し、処理するといったことで使われるようです!
言葉だけではわからないので、実際にコードを書いてみてみましょう。
package main
import (
"fmt"
"sync"
)
func producer(ch chan int, i int) {
// なんらかの処理
ch <- i * 2
}
func consumer(ch chan int, wg *sync.WaitGroup) {
for i := range ch {
fmt.Println("process", i*100)
wg.Done()
}
}
func main() {
var wg sync.WaitGroup
ch := make(chan int)
//Producer
for i := 0; i < 10; i++ {
wg.Add(1)
go producer(ch, i)
}
//Consumer
go consumer(ch, &wg)
wg.Wait()
close(ch)
}
**実行結果**
process 0
process 400
process 200
process 600
process 800
process 1000
process 1200
process 1400
process 1600
process 1800
まず、wg変数とチャネルを作りch変数に格納します。
ここでProducerを生成します。
wg.Add(1)とすることで並行処理の個数をインクリメントしています。(ここでは10回ループさせるのでwgに10個の並行処理があることを伝えている)
そしてproducer関数に引数としてchとiを渡しgoステートメントを付けることで並行処理を走らせます。
producer関数では何らかの処理がされ、i * 2したものをチャネルに送信します。
そして、その処理が終わったらconsumer関数にchとwgのアドレスを渡します。
consumer関数ではproducer関数から送られてきたチャネルの値を取り出しrangeでループ処理をします。ループ処理の内容は、i * 1000 を出力し、wg.Doneでこの処理が終わったことを伝えます。これを10回繰り返しています。
これが終わったら wg.Waitにいき(ここでは処理が10回終わるまで待っている)close(ch)でチャネルが閉じたことを記述します。
ここでの注意点として、consumer自体もGoroutineなので処理が10回終わった後でもまだチャネルから値を取ろうとしており、rangeを回すためにproducer関数からチャネルが送られてくるのを待っています。
producer関数では10回値がチャネルに送られることがわかりますが、consumer関数は10個値が送られてくるなんてことは知らない状態です。チャネルの終わりを告げない限りと次の値をループしようとします。なんて健気なんでしょう。。
ですので、「もうこれ以上producer関数からは値を送信しないよ~」ということをclose(ch)としてチャネルが閉じたことを記述する必要があるのです!
最後まで読んでいただきありがとうございます!
この記事が少しでも理解の助けになれば幸いです!感想やご指摘などあればコメントいただけますと幸いです!