作者 主題: [Golang] Wait for the goroutine end  (閱讀 3814 次)

0 會員 與 1 訪客 正在閱讀本文。

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
[Golang] Wait for the goroutine end
« 於: 2015-08-11 19:25 »
goroutine 有個現象,在 main() 建立 goroutine 後,如果這個函數還沒跑完,
main() 並不會等它結束後才結束整個程式,看個例子

代碼: [選擇]
package main

func main() {
var count int64 = 0
go func() {
for idx := 0; idx < 200; idx++ {
count++
}
}()

println(count)
}

執行結果:

引用
$ go run ex041.go
0

for 迴圈根本就還沒跑到,整個程式就 game over
整理了幾個能讓 goroutine 確實跑完的方式

(1) 利用鍵盤輸入等待

代碼: [選擇]
import (
"fmt"
)

func main() {
var count int64 = 0
go func() {
for idx := 0; idx < 200; idx++ {
count++
}
}()

var in string
fmt.Scanln(&in)
println(count)
}

引用
result:
200

雖然可行,不過迴圈如果要跑很久,會因為按鍵盤時間快慢,迴圈也有可能不會完全跑完


(2) 利用 channel

代碼: [選擇]
func main() {
var count int64 = 0
c1 := make(chan bool)

go func() {
for idx := 0; idx < 200; idx++ {
count++
}
c1 <- true
}()
<-c1
println(count)
}

channel 型態不定要 bool,任何資料型態都可以,整數、字串甚至 struct 也可以

代碼: [選擇]
type MyType struct {
ID   int64
Name string
}

func main() {
var count int64 = 0
c1 := make(chan MyType)

go func() {
for idx := 0; idx < 200; idx++ {
count++
}
c1 <- MyType{}
}()
<-c1
println(count)
}

c1 目的只是要在接收資料時的等待效果。


(3) 使用 sync/WaitGroup

代碼: [選擇]
import (
"sync"
)

func main() {
var count int64 = 0
var wg sync.WaitGroup

wg.Add(1)
go func() {
defer wg.Done()
for idx := 0; idx < 200; idx++ {
count++
}

}()
wg.Wait()
println(count)
}

這個就比較清楚了,在使用 go 之前先告訴系統有一個 goroutine 要等待它跑完

defer wg.Done() 這行是告訴系統『我跑完嘍』

方式 1,2 適合單一 goroutine 或是數量不多時,當 goroutine 數量很多
sync/WaitGroup 就很好用,wg.Wait()會等到所有 goroutine 都結束才放行