我一向認爲一篇 blog 需要使用給出使用場景,纔有借鑑意義,所以本文會先給出使用場景,然後給出解決方案。本文只是記錄,並不代表本人的創新。
在使用 Go 語言的 go 關鍵字的時候,總是有一種錯覺:goroutine 沒有執行。下面給一個簡單的例子:
package main
import (
"fmt"
)
func test() {
fmt.Println("test")
}
func main() {
go test()
fmt.Println("main")
}
得到的輸出基本只有 main 不會有 test。然後我就錯誤地認爲:goroutine 在沒有使用 channel 的時候是不會執行的。當然稍作修改就發現自己錯了,最簡單的就是在最後一行加上
time.sleep(2e9)
這樣一來,main 和 test 都有輸出了。在當前案例可以看出 goroutine 是有執行的。那麼結論應該就是:主線程在新創建的 goroutine 沒有結束的時候直接結束了。那麼我們應該做的是等待新創建的 goroutine 結束,或者用 channel 讓主線程得到新創建的 goroutine 結束的信號再結束。
等待新創建的 goroutine 結束,要使用 sync.WaitGroup
package main
import (
"fmt"
"sync"
)
var waitGroup sync.WaitGroup
func test() {
defer waitGroup.Done()
fmt.Println("test")
}
func main() {
waitGroup.Add(1)
go test()
fmt.Println("main")
waitGroup.Wait()
}
關於 channel 的使用,教程很多,這裏給一個簡單的。注意要創建有緩衝 channel。對了,再記錄一下 Go 語言的名言:不要用共享內存去通信,而要用通信去共享內存。
package main
import (
"fmt"
)
var testStatus = make(chan int, 1)
func test() {
fmt.Println("test")
testStatus <- 0
}
func main() {
go test()
fmt.Println("main")
select {
case _ = <-testStatus:
fmt.Println("finish")
}
}
路漫漫其修遠兮,加油!!