[Golang]並行処理をやってみた!

Go言語には並行処理が簡単にできるよう実装されています。それはGoにあるゴルーチンという機能です。試してみようと思います!

今回作ったものは下のリポジトリに置いときます。

go-dinner

CLIになってますが、記事ではその辺は省いているので上のリポジトリまで。

コード

とりあえずCLIではないコードの全体像をみてください。

package main

import (
  "fmt"
  "time"

  "github.com/kyokomi/emoji"
)

func main() {
    ch := make(chan int, 20)

    sushi := emoji.Sprint("🍣")
    pizza := emoji.Sprint("🍕")
    hamburger := emoji.Sprint("🍔")

    go receive(sushi, ch)
    go receive(pizza, ch)
    go receive(hamburger, ch)

    i := 0
    for i < 10 {
      ch <- i
      i++
    }
    close(ch)

    time.Sleep(2 * time.Second)
}

func receive(name string, ch <-chan int) {
  for {
    _, ok := <-ch
    if ok == false {
      break
    }
    fmt.Println(name)
  }
}

実行すると、ランダムに寿司かハンバーガー、ピザが10個表示されます。

$ go-dinner
🍕
🍕
🍕
🍣
🍔
🍔
🍔
🍔
🍕
🍣

解説

コードを見ていきましょう。

今回は絵文字を使うので、このパッケージを導入しておきましょう。

import (
  "github.com/kyokomi/emoji"
)

for文を使って、チャネルからデータを受信します。受信できなくなったら終了です。

func receive(name string, ch <-chan int) {
  for {
    _, ok := <-ch
    if ok == false {
      break
    }
    fmt.Println(name)
  }
}

次にmain()を見ていきます。

sushi := emoji.Sprint("🍣")
pizza := emoji.Sprint("🍕")
hamburger := emoji.Sprint("🍔")

使う絵文字を定義します。

次にチャネルを生成します。

ch := make(chan int, 20)

そして、go文を使いゴルーチンを三つ起動します。

go receive(sushi, ch)
go receive(pizza, ch)
go receive(hamburger, ch)

チャネルを閉じて、ゴルーチンの終了を待ちます。

close(ch)

time.Sleep(2 * time.Second)

実行してみるとランダムに出力されていると思います。

どんな風にiが割り当てられているか見たいなら、receiver()の中を下のようにしてみてください。数値とともに出力されるはずです。

func receive(name string, ch <-chan int) {
  for {
    i, ok := <-ch
    if ok == false {
      break
    }
    fmt.Println(name, i)
  }
}

Golangでは並行処理をものすごく簡単に実装できますね。