📑

GOを1から学ぶ #7

に公開

初めに

こんにちは!技術スタック的には、フロントよりですが、GOを学ぶ機会があったので、その記録を取りたいと思いこの記事を書いてます。(初心者のため優しい目で見てください)
今回は、以下について簡単にまとめます。

  • 並行処理について

Goroutine(ゴルーチン)とは?

Goroutine(ゴルーチン)は、関数やメソッドを同時に実行(並行処理) するための仕組み。goを関数の前につけるだけで、新しいGoroutineが作成可能。

基本構文

go 関数名(引数)

具体的な例:2つのタスクを並行実行する

package main

import (
    "fmt"
    "time"
)

func task1() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task 1 -", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func task2() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task 2 -", i)
        time.Sleep(150 * time.Millisecond)
    }
}

func main() {
    go task1()  // 並行実行
    go task2()  // 並行実行

    time.Sleep(1 * time.Second) // 並行処理が終わるまで待機
    fmt.Println("All tasks completed")
}

実行結果
Task 2 - 0
Task 1 - 0
Task 1 - 1
Task 2 - 1
Task 1 - 2
Task 1 - 3
Task 2 - 2
Task 1 - 4
Task 2 - 3
Task 2 - 4
All tasks completed

sync.WaitGroup

sync.WaitGroup とは
Goでは go キーワードを使って複数の処理(ゴルーチン)を並行して実行可能だが、すべてのゴルーチンが終わるまで待ちたい場合に sync.WaitGroup が使われる。
たとえば、3つのゴルーチンで並列処理を行い、それらが全部終わってから次の処理をしたい場合などに役立つ。Add() で待つゴルーチン数を指定し、各ゴルーチンで Done() を呼び、最後に Wait() で完了を待つ。
基本的な構文

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup // WaitGroup を作成

    wg.Add(2) // ゴルーチンを2つ待つ

    go func() {
        defer wg.Done() // ゴルーチン1の終了を通知
        fmt.Println("ゴルーチン1の処理")
    }()

    go func() {
        defer wg.Done() // ゴルーチン2の終了を通知
        fmt.Println("ゴルーチン2の処理")
    }()

    wg.Wait() // すべてのゴルーチンの完了を待つ
    fmt.Println("すべての処理が完了しました")
}

実行結果
ゴルーチン2の処理
ゴルーチン1の処理
すべての処理が完了しました

具体的な例

package main

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

func task1(wg *sync.WaitGroup) {
    defer wg.Done() // 処理が終わったら Done を呼ぶ

    for i := 0; i < 5; i++ {
        fmt.Println("Task 1 -", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func task2(wg *sync.WaitGroup) {
    defer wg.Done()

    for i := 0; i < 5; i++ {
        fmt.Println("Task 2 -", i)
        time.Sleep(150 * time.Millisecond)
    }
}

func main() {
    var wg sync.WaitGroup

    wg.Add(2) // 並行実行するタスクの数を指定

    go task1(&wg) // Goroutine を起動
    go task2(&wg)

    wg.Wait() // すべての Done を待つ
    fmt.Println("All tasks completed")
}

実行結果
Task 2 - 0
Task 1 - 0
Task 1 - 1
Task 2 - 1
Task 1 - 2
Task 1 - 3
Task 2 - 2
Task 1 - 4
Task 2 - 3
Task 2 - 4
All tasks completed

sync.WaitGroup使用の判断

Channel(チャネル)とは?

Go言語の Channel(チャネル) とは、ゴルーチン(goroutine)間でデータをやり取りするための仕組み。

チャネルの概要

チャネルはパイプのようなもので、あるゴルーチンがチャネルにデータを送信し、別のゴルーチンがそのデータを受信する。また、チャネルはある特定の型の値だけを送受信できます。

基本構文

// チャネルの作成
ch := make(chan int)

// チャネルに値を送信
ch <- 10

// チャネルから値を受信
x := <-ch

ゴルーチンとチャネルの組み合わせ

package main

import (
    "fmt"
)

// 数字を2倍にしてチャネルに送る関数
func double(num int, ch chan int) {
    result := num * 2
    ch <- result  // チャネルに送信
}

func main() {
    ch := make(chan int)  // チャネル作成

    go double(5, ch)       // ゴルーチンで関数を実行

    result := <-ch         // チャネルから値を受信(完了するまで待つ)

    fmt.Println(result)    // 出力: 10
}

実行結果
10

Discussion