見出し画像

[Go言語 入門] Goroutin

golangで作ってみたいものがあり、golangを学び始めたので学習したことを書いていくノート。

---------------------------------------------------

サイトマップはこちら

---------------------------------------------------

第17回 Goroutin


Goroutin とは並列処理のこと。

通常プログラムは、main関数の上から下に実行されていく。

func hello() {
	for i := 0; i < 5; i++ {
		fmt.Println("Hello")
	}
}

func world() {
	for i := 0; i < 5; i++ {
		fmt.Println("World")
	}
}
func main() {
	hello()
	world()
}
// 実行結果
// Hello
// Hello
// Hello
// Hello
// Hello
// World
// World
// World
// World
// World

上記のプログラムを、Goroutineを使い並列処理化していく。

Goroutineは以下のように記述する。

「go 関数名()」

// main.go

func hello() {
	for i := 0; i < 5; i++ {
		time.Sleep(50 * time.Millisecond)
		fmt.Println("Hello")
	}
}

func world() {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println("World")
	}
}
func main() {
	go hello()
	world()
}

// 実行結果
// Hello
// World
// World
// Hello
// Hello
// World
// World
// Hello
// Hello
// World

0.1秒分 time.Sleep を加えたのは、world関数が実行完了してしまうと、並列処理中のhello関数も実行が終了してしまうため。

並列処理中の関数の実行も待つ場合どのようにすればよいか。

「sync.WaitGroup」を使う。

sync.WaitGroupを使ったプログラムは以下。

// main2.go

func hello(wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < 5; i++ {
		fmt.Println("Hello")
	}
}

func world() {
	for i := 0; i < 5; i++ {
		fmt.Println("World")
	}
}
func main() {
	var wg sync.WaitGroup
	wg.Add(1)
	go hello(&wg)
	world()

	wg.Wait()
}

// 実行結果
// World
// World
// World
// World
// World
// Hello
// Hello
// Hello
// Hello
// Hello

まずは、main関数で「var wg sync.WaitGroup」を宣言した。

宣言した wg にmain関数内にあるGoroutineの数を渡す。(ここではhello関数の1個分)

GoroutineのHello関数に sync.WaitGroup の wg のアドレスを渡し、hello関数内で、関数の実行が完了したことを伝える「wg.Done()」を記述する。(deferで宣言または関数の一番最後に宣言)

「wg.Done()」「wg.Add(n)」の n個分実行されるまでmain関数の完了を待つ「wg.Wait()」をmain関数に記述する。

上記のようにすることで、Goroutineがすべて完了するまでmain関数が終了しないようにすることができる。


※Goroutineではreturn で値を返すことができないので注意!

値を返す場合はchannelを使う。



この記事が気に入ったらサポートをしてみませんか?