Go言語で並列処理をする方法
Go言語での並列処理は、主に「goroutine」と「channel」という2つの主要な機能を使って実現します。
これにより、効率的にタスクを並行して実行し、パフォーマンスを向上させることが可能です。
1. goroutine
Go言語では、goroutineを使用して軽量なスレッドを作成します。
goroutineは、並行して実行される関数やメソッドの呼び出しを提供します。
goroutineは、goキーワードを関数呼び出しの前に付けることで作成できます。
package main import ( "fmt" "time" ) func sayHello() { for i := 0; i < 5; i++ { fmt.Println("Hello") time.Sleep(time.Second) } } func main() { go sayHello() // sayHello関数をgoroutineとして実行 time.Sleep(6 * time.Second) // メインゴルーチンが終了する前に待機 }
この例では、sayHello関数がgoroutineとして実行され、メインのゴルーチンと並行して動作します。
time.Sleepを使ってメインのゴルーチンが終了する前に待機しています。
2. channel
channelは、goroutine間でデータを通信するための同期手段です。
channelを使うことで、goroutine間でデータを安全に受け渡しできます。
channelは、make関数を使って作成します。
package main import ( "fmt" ) func sendData(ch chan<- int) { for i := 0; i < 5; i++ { ch <- i // チャネルにデータを送信 } close(ch) // チャネルをクローズ } func receiveData(ch <-chan int) { for data := range ch { fmt.Println(data) // チャネルからデータを受信 } } func main() { ch := make(chan int) // チャネルを作成 go sendData(ch) // データ送信用のgoroutine receiveData(ch) // メインゴルーチンでデータ受信 }
この例では、sendData関数がデータをchannelを通じて送信し、receiveData関数がそれを受信します。
channelを通じてデータの送受信を行うことで、データの整合性を保ちながら並列処理を実現します。
3. Select文
select文を使用すると、複数のchannelからの送受信を待機し、どのchannelが最初に準備できるかに応じて処理を行います。
select文は、複数のchannelを扱う場合に非常に便利です。
package main import ( "fmt" "time" ) func main() { ch1 := make(chan string) ch2 := make(chan string) go func() { time.Sleep(2 * time.Second) ch1 <- "Message from ch1" }() go func() { time.Sleep(1 * time.Second) ch2 <- "Message from ch2" }() select { case msg1 := <-ch1: fmt.Println(msg1) case msg2 := <-ch2: fmt.Println(msg2) } }
この例では、ch1とch2の2つのchannelからのメッセージをselect文を使って待機し、どちらかのchannelからメッセージが受信されると、それを処理します。
select文は、複数のchannel操作を同時に管理する際に役立ちます。
4. WaitGroup
sync.WaitGroupを使うことで、複数のgoroutineの終了を待機することができます。
WaitGroupは、Add、Done、Waitの3つのメソッドを持ちます。
package main import ( "fmt" "sync" ) func worker(wg *sync.WaitGroup, id int) { defer wg.Done() // 作業が終了したらDoneを呼び出す fmt.Printf("Worker %d started\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 3; i++ { wg.Add(1) // WaitGroupに1つのgoroutineを追加 go worker(&wg, i) } wg.Wait() // すべてのgoroutineの終了を待機 fmt.Println("All workers completed") }
この例では、worker関数を3つのgoroutineで並行して実行し、WaitGroupを使ってすべてのworkerが終了するまでメインゴルーチンが待機します。
WaitGroupは、並行処理の終了管理に非常に有用です。
Go言語の並列処理は、これらの機能を組み合わせることで、シンプルで強力な並行プログラムを構築することができます。
goroutineを使って並行処理を実行し、channelでデータの送受信を行い、selectやWaitGroupで処理の管理をすることで、効率的なプログラムを作成できます。