goroutine 的生命週期
go f() 啟動 goroutine;f 返回時,這個 goroutine 才結束。呼叫它的函式返回,不會自動取消它。
若 main 返回,整個程式會結束,其他 goroutine 不會被等待。語言規格(另開分頁)
啟動工作前,先確定兩件事:
- 正常完成時,誰等待它?例如
WaitGroup.Wait。 - 結果不再需要時,它如何退出?例如監聽
ctx.Done()。
WaitGroup 只負責等待;取消必須由工作本身配合。
go f() 啟動 goroutine;f 返回時,這個 goroutine 才結束。呼叫它的函式返回,不會自動取消它。
若 main 返回,整個程式會結束,其他 goroutine 不會被等待。語言規格(另開分頁)
啟動工作前,先確定兩件事:
WaitGroup.Wait。ctx.Done()。WaitGroup 只負責等待;取消必須由工作本身配合。
go f() 讓 f 在新的 goroutine 執行,呼叫者繼續往下走。它不會自動等待 f 完成。1
先啟動一件工作,再用 sync.WaitGroup 等它結束:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("工作完成")
}()
wg.Wait()
fmt.Println("main 結束")
}
這兩行的順序是否固定?若移除 wg.Wait(),還能保證看見「工作完成」嗎?
輸出固定是:
工作完成
main 結束
工作先印字,返回時執行 Done();計數歸零,Wait() 才返回。
移除 Wait() 後,工作可能尚未執行,main 就已返回。程式不會替其他 goroutine 等待。2
這裡的 Add(1) 必須放在 go 前面。若移進 goroutine,main 可能先看見零計數,讓 Wait() 直接返回。defer wg.Done() 則把扣除計數放在工作返回時。3
WaitGroup 負責等待,不傳回計算結果,也不限制工作數量。把 Wait() 換成 time.Sleep 只能猜工作要多久,不能建立完成順序。每次啟動工作,都要安排它如何退出:goroutine 的生命週期。
go f() 啟動 goroutine;f 返回時,這個 goroutine 才結束。呼叫它的函式返回,不會自動取消它。
若 main 返回,整個程式會結束,其他 goroutine 不會被等待。語言規格(另開分頁)
啟動工作前,先確定兩件事:
WaitGroup.Wait。ctx.Done()。WaitGroup 只負責等待;取消必須由工作本身配合。