跳至主要內容
yomihon 書庫
整體狀況設定

鍵盤快捷鍵

⌘K / Ctrl K
搜尋
Esc
關閉搜尋或篩選
/
跳到導覽篩選(單鍵開啟時)
[
收合或展開側欄(單鍵開啟時)

關掉之後,/ 和 [ 都只會照瀏覽器原本的方式輸入;⌘K 與 Esc 不受影響。

設定
esc

↑↓ 選擇 ↵ 搜尋 esc 關閉

goroutine 的生命週期

concept檔案變更於
檔案變更於
類型
concept
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
檔案變更於
類型
concept
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
聲明的來源 1 對照閱讀 1 正文連到這篇 2

go f() 啟動 goroutine;f 返回時,這個 goroutine 才結束。呼叫它的函式返回,不會自動取消它。

若 main 返回,整個程式會結束,其他 goroutine 不會被等待。語言規格(另開分頁)

啟動工作前,先確定兩件事:

  • 正常完成時,誰等待它?例如 WaitGroup.Wait。
  • 結果不再需要時,它如何退出?例如監聽 ctx.Done()。

WaitGroup 只負責等待;取消必須由工作本身配合。

G01 goroutine 與等待

lesson檔案變更於
檔案變更於
類型
lesson
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
檔案變更於
類型
lesson
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
本頁內容 以這篇為來源的筆記 1 對照閱讀 1 正文連到這篇 2

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 的生命週期。