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

鍵盤快捷鍵

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

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

設定
esc

↑↓ 選擇 ↵ 搜尋 esc 關閉

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

作者標記的狀態 ready
設為 archived

設為 archived 之後,這裡不再有回到目前狀態的路。