Go言語による効率的な並列処理:初心者から上級者まで

Go言語は、その高速な実行速度と並列処理の容易さで知られています。この記事では、Go言語を使用した並列処理の基本から、より高度なテクニックまでを解説します。初心者から上級者まで、Go言語の並列処理を深く理解し、実践的なコード例を通して学んでいきましょう。

コード例1:ゴルーチンの基本

ゴルーチンはGo言語の並列処理の中核をなす機能です。以下の例では、シンプルなゴルーチンの使い方を示します。

package main

import (
    "fmt"
    "time"
)

func printNumbers() {
    for i := 1; i <= 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(i)
    }
}

func main() {
    go printNumbers()
    fmt.Println("Hello, Go!")
    time.Sleep(500 * time.Millisecond)
}

このコードでは、printNumbers関数をゴルーチンとして実行しています。main関数は独立して実行され、ゴルーチンはバックグラウンドで数を印刷します。

コード例2:チャネルを使用したデータの交換

チャネルはゴルーチン間でのデータの交換に使用されます。以下のコードは、チャネルを使用してゴルーチン間でデータを送受信する方法を示しています。

package main

import (
    "fmt"
    "time"
)

func sendData(ch chan string) {
    time.Sleep(1 * time.Second)
    ch <- "データ1"
    time.Sleep(1 * time.Second)
    ch <- "データ2"
}

func main() {
    ch := make(chan string)
    go sendData(ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

この例では、sendData関数がチャネルを通じてメイン関数にデータを送信します。

コード例3:WaitGroupを使用したゴルーチンの同期

ゴルーチンを効率的に同期させるために、sync.WaitGroupを使用することができます。

package main

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

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }

    wg.Wait()
    fmt.Println("All workers done")
}

このコードでは、WaitGroupを使用して、すべてのゴルーチンが完了するのを待ちます。

コード例4:並列処理におけるエラー処理

並列処理ではエラー処理も重要です。以下のコードは、ゴルーチン内で発生したエラーをメイン関数に伝える方法を示しています。

package main

import (
    "fmt"
    "time"
    "errors"
)

func process(task int) (int, error) {
    if task < 0 {
        return 0, errors.New("負のタスクは処理できません")
    }
    time.Sleep(time.Duration(task) * time.Second)
    return task * 2, nil
}

func main() {
    tasks := []int{3, 2, -1, 0, 1}
    results := make(chan string)

    for _, task := range tasks {
        go func(task int) {
            result, err := process(task)
            if err != nil {
                results <- err.Error()
            } else {
                results <- fmt.Sprintf("結果: %d", result)
            }
        }(task)
    }

    for i := 0; i < len(tasks); i++ {
        fmt.Println(<-results)
    }
}

このコードでは、process関数がエラーを返す可能性があり、そのエラーをメイン関数で処理しています。

まとめ

Go言語の並列処理は、効率的かつ強力です。この記事で紹介したコード例を通じて、並列処理の基本から応用までを学ぶことができます。実践的なコードとともに、Go言語の並列処理の魅力を存分に体験しましょう。

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