技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

channelを経由した関数間の引き渡し【Go】

channelに値を送信する関数と、
channelから値を受信して処理をする関数を作成し、
sync.WaitGroupを使って並行処理を行います。

func producer(c chan int, i int) {
    c <- i * 3
}

func consumer(c chan int, wg *sync.WaitGroup) {
    for v := range c {
        func() {    // 無名関数化することで、処理(この例ではfmt.Println(v, *wg))に問題があってもDoneが呼ばれるようになり、止まるのを防ぐ
            defer wg.Done()    // 無名関数内の処理が終わったらwgが管理する個数を1つ減らす
            fmt.Println(v, *wg)    // *wgで、wgの個数が減少する様子を確認できる
        }()
    }
    fmt.Println("*************")    // wg.Wait()完了後にclose()し、時間待ちすることで出力される
}

func main() {
    var wg sync.WaitGroup
    c := make(chan int, 10)

    for i := 0; i < 10; i++ {
        wg.Add(1)    // forループの個数分、wgが管理する個数を追加する
        go producer(c, i)    // 擬似的に複数処理を生成する
    }
    go consumer(c, &wg)
    wg.Wait()    // consumer内で、全てDoneされるまで待つ
    close(c)    // closeすることで、consumer内のchannelのfor rangeループが終点を認識し、ループから抜けることができる
    time.Sleep(1 * time.Millisecond)    // consumer内のchannelのfor rangeループから抜けたことを確認するために、時間待ちをする必要がある
    fmt.Println("Done")
}

いくつかの処理から並行して値を受け取り、
channelを通して出力する処理を行なっています。