はじめに
Go言語は並列処理を容易に実現するための強力な機能を備えています。
特にゴルーチン(goroutines)という軽量スレッドの概念を使って、並行処理を実装できます。
そして、チャネル(channel)という機能を使うことで、複数のゴルーチン間でデータの受け渡しを行うことができます。
この記事では、ゴルーチン チャネル を使った並行処理の実装方法を説明します。
ゴルーチンとは
ゴルーチンとは、Go言語のランタイムによって管理される軽量スレッドです。
ゴルーチンは、スレッドよりもメモリ使用量が少なく、スレッドの切り替えにかかる時間も短いため、
多数のゴルーチンを同時に実行しても、メモリやCPUの負荷が大きく増加しないのが特徴です。
ゴルーチンの使用例
package main
import (
"fmt"
"time"
)
// 2. タスクの実行
func task(name string) {
for i := 0; i < 5; i++ {
fmt.Println(name, ":", i) // nameとカウンター値を出力
time.Sleep(time.Millisecond * 500) // 0.5秒待機
}
}
func main() {
// 1. ゴルーチンの起動
go task("goroutine1")
go task("goroutine2")
// 3. 待機
time.Sleep(time.Second * 3)
fmt.Println("メイン関数終了")
}
実行結果
並列処理のため実行するたびに順序は異なります
$ go run main.go
goroutine2 : 0
goroutine1 : 0
goroutine2 : 1
goroutine1 : 1
goroutine1 : 2
goroutine2 : 2
goroutine2 : 3
goroutine1 : 3
goroutine1 : 4
goroutine2 : 4
メイン関数終了
コードの説明
-
ゴルーチンの起動:goキーワードを使うと、関数をゴルーチンとして起動できます。例:go task("goroutine1")。
この例では、task関数を2つの異なるゴルーチンで並行して実行します。 -
タスクの実行:各ゴルーチンは、task関数を独立して実行し、名前とカウンター値を出力します。
-
待機:main関数は、ゴルーチンが完了するまで少し待機する必要があります。
これは、main関数が終了するとプログラム全体が終了し、実行中のゴルーチンも中断されるためです。
チャネルとは
チャネルとは、ゴルーチン間でデータの受け渡しを行うための機能です。
チャネルは、チャネル型の変数を宣言することで作成できます。
チャネルの使用例
package main
import (
"fmt"
"time"
)
// sendMessages関数は、特定のメッセージをチャネルに送信します
// 3. ゴルーチンで実行される関数
func sendMessages(c chan string, message string) {
for i := 0; i < 3; i++ {
c <- fmt.Sprintf("%s %d", message, i) // チャネルにメッセージを送信
time.Sleep(time.Second) // 次のメッセージ送信まで待機
}
}
func main() {
// 1. チャネルの作成
messageChan := make(chan string)
// 2. 複数のゴルーチンを並列で実行
go sendMessages(messageChan, "goroutine1")
go sendMessages(messageChan, "goroutine2")
go sendMessages(messageChan, "goroutine3")
// 4. チャネルからメッセージを受信して出力
for i := 0; i < 9; i++ {
fmt.Println(<-messageChan) // チャネルからメッセージを受信
}
}
実行結果
並列処理のため実行するたびに順序は異なります
$ go run main.go
goroutine3 0
goroutine1 0
goroutine2 0
goroutine2 1
goroutine1 1
goroutine3 1
goroutine1 2
goroutine2 2
goroutine3 2
コードの説明
- チャネルの作成:make(chan string)により、string型のデータを転送するためのチャネルmessageChanを作成しています。
- 複数のゴルーチンの起動:go sendMessages(messageChan, "goroutine1")などで、sendMessages関数をゴルーチンとして起動し、異なるメッセージで3つのゴルーチンを並列に実行します。
- ゴルーチンの関数:sendMessages関数はゴルーチンで実行され、チャネルにメッセージを送信します。
- チャネルからの受信と出力:メインゴルーチンはチャネルmessageChanからメッセージを受信し、それを出力します。それぞれ独立しているため、競合状態は発生しないのが特徴です。
まとめ
ゴルーチンとチャネルを使うことで、Go言語では簡単に並行処理を実装できます!