PR

Go言語(Golang)のchannel(チャネル)型でgoroutine(ゴールーチン)間のデータを送受信!

基礎

こんにちは。Tomoyuki(@tomoyuki65)です。

Go言語(Golang)にはchannel(チャネル)型というのがあり、これを使うことでgoroutine(ゴールーチン)間のデータを送受信できます。

 

Go言語(Golang)はgoroutine(ゴールーチン)で並行処理が可能!
こんにちは。Tomoyuki(@tomoyuki65)です。 Go言語(Golang)ではgoroutine(ゴールーチン)を使うことによって並行処理が可能なため、上手く使えばパフォーマンス改善に繋がります! ※プログラムは通常一行ずつ処理...

 

Go言語(Golang)のchannel(チャネル)型でgoroutine(ゴールーチン)間のデータを送受信!

goroutineを使って並行処理をすると非同期で関数を実行することになりますが、その際にchannel(チャネル)型を使うと非同期関数内で処理した値を別の関数へ送信して使うことができるようになります。

例えば以下のプログラムを実行してみて下さい。

package main

import (
    "fmt"
    "time"
    "sync"
)

// 関数のパラメータに受信用のチャネル型「<-chan」を設定
func wait50ms(wg *sync.WaitGroup, c <-chan string) {
    time.Sleep(time.Millisecond * 50)

    fmt.Println("チャネルから値を受信開始")
    str := <-c
    fmt.Println("チャネルから値を受信完了")

    // チャネルから受信した値を表示
    fmt.Println(str)

    wg.Done()
}

// 関数のパラメータに送信用のチャネル型「chan<-」を設定
func wait100ms(wg *sync.WaitGroup, c chan<- string) {
    time.Sleep(time.Millisecond * 100)

    fmt.Println("チャネルに値を送信開始")
    c <- "wait100ms関数内からチャネルに値を送信!"
    fmt.Println("チャネルに値を送信完了")

    wg.Done()
}


func main() {
    elapsedTime := time.Now()

    // string型の値を送受信するためのチャネルを作成
    c := make(chan string)

    var wg sync.WaitGroup
    wg.Add(2)

    go wait50ms(&wg, c)
    go wait100ms(&wg, c)

    wg.Wait()

    // チャネルを閉じる
    close(c)

    fmt.Println("経過時間:", time.Since(elapsedTime))
}

 

実行結果は以下のようになります。

チャネルから値を受信開始
チャネルに値を送信開始
チャネルに値を送信完了
チャネルから値を受信完了
wait100ms関数内からチャネルに値を送信!
経過時間: 100ms

 

このようにchannel型を使えばgoroutine間での値の送受信が可能です。

また、channel型はデフォルトで一つの値ずつしか送受信ができず、例えば値を送信した後はその値が受信されるまで送信側の処理が止まるため、送信側と受信側で同期的な処理をさせたい場合に使います。

そしてchannelにはバッファを設定することで複数の値の送受信が可能になりますが、その場合は非同期的な処理になります。

例えば以下のようにchannelにバッファを設定するよう修正してみて下さい。

package main

import (
    "fmt"
    "time"
    "sync"
)

// 関数のパラメータに受信用のチャネル型「<-chan」を設定
func wait50ms(wg *sync.WaitGroup, c <-chan string) {
    time.Sleep(time.Millisecond * 50)

    fmt.Println("チャネルから値を受信開始")
    str := <-c
    fmt.Println("チャネルから値を受信完了")

    // チャネルから受信した値を表示
    fmt.Println(str)

    wg.Done()
}

// 関数のパラメータに送信用のチャネル型「chan<-」を設定
func wait100ms(wg *sync.WaitGroup, c chan<- string) {
    time.Sleep(time.Millisecond * 100)

    fmt.Println("チャネルに値を送信開始")
    c <- "wait100ms関数内からチャネルに値を送信!"
    c <- "2個目の値を送信!"
    fmt.Println("チャネルに値を送信完了")

    wg.Done()
}


func main() {
    elapsedTime := time.Now()

    // string型の値を送受信するためのチャネルを作成
    // バッファには2を設定
    c := make(chan string, 2)

    var wg sync.WaitGroup
    wg.Add(2)

    go wait50ms(&wg, c)
    go wait100ms(&wg, c)

    wg.Wait()

    // チャネルに送信した2個目の値を受信して表示
    str := <-c
    fmt.Println("main関数:", str)

    // チャネルを閉じる
    close(c)

    fmt.Println("経過時間:", time.Since(elapsedTime))
}

 

実行結果は以下のようになります。

チャネルから値を受信開始
チャネルに値を送信開始
チャネルに値を送信完了
チャネルから値を受信完了
wait100ms関数内からチャネルに値を送信!
main関数: 2個目の値を送信!
経過時間: 100ms

 

スポンサーリンク

最後に

今回はchannel(チャネル)型についてご紹介しました。

goroutineで並行処理をする際に使うことが出てくる可能性があるため、goroutineと合わせてchannelについても覚えておきましょう。

 

この記事を書いた人
Tomoyuki

SE→ブロガーを経て、現在はWeb系エンジニアをしています!

Tomoyukiをフォローする
基礎
スポンサーリンク
Tomoyukiをフォローする

コメント

タイトルとURLをコピーしました