Go のゴルーチン(Goroutine)

ゴルーチン(Goroutine)

ゴルーチンは Go で並行処理を実現する仕組みである。軽量であり、複数の処理を効率よく並行実行できる。

次の例では、メインの処理を実行しながら、go を使って funcA() をゴルーチンとして実行する。

package main

import (
	"fmt"
	"time"
)

func funcA() {
	for i := 0; i < 10; i++ {
		fmt.Print("A")
		time.Sleep(10 * time.Millisecond)
	}
}

func main() {
	go funcA()
	for i := 0; i < 10; i++ {
		fmt.Print("M")
		time.Sleep(20 * time.Millisecond)
	}
}

実行結果:

MAAMAAAMAAMAAMAMMMMM

次の例では、チャネルを使ってゴルーチンの終了を待つ。chan はチャネル型を宣言し、<- はチャネルを通じてメッセージを送受信する。

package main

import (
	"fmt"
	"time"
)

func funcA(chA chan<- string) {
	time.Sleep(3 * time.Second)
	chA <- "Finished" // チャネルへメッセージを送信する
}

func main() {
	chA := make(chan string) // チャネルを作成する
	defer close(chA)         // 使用後に閉じる
	go funcA(chA)            // ゴルーチンを開始する
	msg := <-chA             // チャネルからメッセージを受信する
	fmt.Println(msg)
}

実行結果:

Finished

次の例では、select を使って funcA()funcB() の両方を待つ。

package main

import (
	"fmt"
	"time"
)

func funcA(chA chan<- string) {
	time.Sleep(1 * time.Second)
	chA <- "funcA Finished"
}

func funcB(chB chan<- string) {
	time.Sleep(2 * time.Second)
	chB <- "funcB Finished"
}

func main() {
	chA := make(chan string)
	chB := make(chan string)
	defer close(chA)
	defer close(chB)
	finflagA := false
	finflagB := false
	go funcA(chA)
	go funcB(chB)
	for {
		select {
		case msg := <-chA:
			finflagA = true
			fmt.Println(msg)
		case msg := <-chB:
			finflagB = true
			fmt.Println(msg)
		}
		if finflagA && finflagB {
			break
		}
	}
}

実行結果:

funcA Finished
funcB Finished