[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を使う。