關於 Goroutine 的一些使用細節

我一向認爲一篇 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")
    }
}

路漫漫其修遠兮,加油!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章