Go 並行回顧 2026-09-22
本頁內容 正文連到這篇 1
Go 並行回顧
只收第一個值,誰還沒結束?
producer 依序送出 2、4、6;consumer 收到 2 就返回。若用無緩衝 channel,後面又沒人接收,producer 會卡在送出 4。consumer 返回,不會連帶終止 producer。
讓傳送同時等待接收者或取消通知:
select {
case out <- value:
case <-ctx.Done():
return
}
consumer 不再需要結果時呼叫 cancel。這裡只有一個 producer,由它在 goroutine 開頭安排 defer close(out),結束時關閉輸出。
三個邊界
| 機制 | 能做什麼 | 不能保證什麼 |
|---|---|---|
| channel | 無緩衝 send 等到接收者就緒;有緩衝時可先填入空位 | 接收者離開後,sender 會自行結束 |
| close | 表示不再送值;已緩衝的值仍可取出,耗盡後 receive 得到零值與 false | 取消還在執行的 goroutine;向已關閉 channel 傳送會 panic |
| context | 透過 Done 通知工作取消 | 強制中斷工作,或等待工作結束 |
取消是合作機制。迴圈必須檢查 Done;阻塞的 I/O 也要支援 context。若 send 與 Done 同時就緒,select 可能選到 send,不能假設取消有優先權。
工作變多時
固定啟動 N 個 worker,從 jobs channel 取工作,可限制同時執行的工作數。任務佇列與結果 channel 也要有容量與取消策略,不能只限制 worker 數就宣稱記憶體有上限。
多個 worker 共用輸出時,由協調者等待所有 sender 結束,再關閉輸出;不要讓每個 worker 各自 close。需要確認全部退出時,用 WaitGroup 等待,不能以 cancel 返回代替。
依據
- Go 官方:Pipelines and cancellation(另開分頁) — 提前停止接收、取消、固定 worker 與關閉輸出的責任。
- context 文件(另開分頁) — Done 與取消;CancelFunc 不等待工作結束。
- Go 語言規格:Send statements(另開分頁)、Close(另開分頁)、Select statements(另開分頁) — 阻塞、關閉與就緒分支的選擇。