Go言語で並行処理をする方法
Go言語で並行処理を行うには、主に「ゴルーチン」と「チャネル」を使います。
Goは並行処理のためのサポートが豊富で、これにより複数の処理を効率よく実行できます。
ゴルーチン
ゴルーチンは、Go言語の並行処理の基本単位です。
関数やメソッドをゴルーチンとして実行するには、関数呼び出しの前にキーワード go を付けます。
これにより、指定した関数が新しいゴルーチンとして非同期に実行されます。
ゴルーチンは軽量で、システムのスレッドよりも少ないリソースで並行処理を実現できます。
以下に、ゴルーチンの基本的な使用例を示します。
package main import ( "fmt" "time" ) func sayHello() { for i := 0; i < 5; i++ { fmt.Println("Hello") time.Sleep(1 * time.Second) } } func sayGoodbye() { for i := 0; i < 5; i++ { fmt.Println("Goodbye") time.Sleep(1 * time.Second) } } func main() { go sayHello() // ゴルーチンとして実行 go sayGoodbye() // ゴルーチンとして実行 // メインゴルーチンが終了する前に、サブゴルーチンの処理が終了するのを待つ time.Sleep(6 * time.Second) }
このコードでは、sayHello と sayGoodbye の2つの関数がゴルーチンとして並行に実行されます。
time.Sleep を使用してメインゴルーチンがサブゴルーチンの終了を待っていますが、実際のアプリケーションでは sync.WaitGroup などを使用してゴルーチンの完了を待機することが推奨されます。
チャネル
チャネルは、ゴルーチン間でデータをやり取りするための通信手段です。
チャネルを使うことで、ゴルーチン間の同期やデータ共有を簡単に行うことができます。
チャネルの基本的な操作には、送信(<- 演算子を使う)と受信(<- 演算子を使う)が含まれます。
以下に、チャネルを使った例を示します。
package main import ( "fmt" "time" ) func generateNumbers(ch chan int) { for i := 1; i <= 5; i++ { ch <- i // チャネルに値を送信 time.Sleep(1 * time.Second) } close(ch) // チャネルを閉じる } func main() { ch := make(chan int) // チャネルの作成 go generateNumbers(ch) // ゴルーチンとして実行 for num := range ch { // チャネルから値を受信 fmt.Println(num) } }
この例では、generateNumbers 関数が整数をチャネルに送信し、メインゴルーチンがその整数を受信して表示します。
チャネルが閉じられると、range ループは自動的に終了します。
同期
ゴルーチンが完了するのを待機するためには、sync.WaitGroup を使うことが一般的です。
以下にその例を示します。
package main import ( "fmt" "sync" ) func printNumbers(wg *sync.WaitGroup) { defer wg.Done() for i := 1; i <= 5; i++ { fmt.Println(i) } } func main() { var wg sync.WaitGroup wg.Add(1) // ゴルーチンの数を追加 go printNumbers(&wg) // ゴルーチンとして実行 wg.Wait() // ゴルーチンが完了するのを待機 }
sync.WaitGroup を使用することで、メインゴルーチンがサブゴルーチンの完了を待機し、正確に同期処理を行うことができます。
このように、Go言語ではゴルーチンとチャネルを駆使することで、並行処理を簡潔かつ効率的に実現できます。
並行処理を効果的に活用することで、パフォーマンスの向上やレスポンシブなアプリケーションの構築が可能になります。