Go Unbounded Goroutine Anti-Pattern¶
概念概覽
三種 Fire-and-Forget 反模式¶
核心知識¶
三種 Fire-and-Forget 反模式¶
1. Admin Audit — 無 WaitGroup 追蹤¶
// 反模式:goroutine 啟動後主程式不追蹤
go func() { auditLog(event) }()
// 修復:外層加 WaitGroup + shutdown hook
wg.Add(1)
go func() {
defer wg.Done()
auditLog(event)
}()
// shutdown: wg.Wait()
2. GDPR Export — 無 Semaphore 上界¶
// 反模式:每個請求無限制啟動 goroutine
go func() { exportUserData(userID) }()
// 修復:加 semaphore 上界(建議 50)
sem <- struct{}{}
go func() {
defer func() { <-sem }()
exportUserData(userID)
}()
3. Dungeon S3 Upload — Pool 滿時 Silent Drop¶
// 反模式:pool 滿時靜默丟棄任務
select {
case pool <- task:
default: // 靜默丟棄
}
// 修復:pool 滿時 fail-fast(返回 error,讓上層決策)
select {
case pool <- task:
default:
return ErrPoolFull
}
判斷標準(何時是 P0)¶
fire-and-forget goroutine 若同時滿足以下條件之一,則為 P0: - 無 WaitGroup → graceful shutdown 時資料遺失 - 無上界(semaphore/pool) → 資源耗盡攻擊面 - Silent drop → 資料遺失無可見性
經驗教訓¶
-
Fire-and-forget goroutine 在低流量下不會暴露問題,只有 graceful shutdown 或高並發時才出現
-
三種反模式修復方向不同:WaitGroup 解決關閉時遺失、Semaphore 解決無界放大、fail-fast 解決靜默丟棄
-
P0 判定依據是「資料是否可能靜默遺失」,而非「程式是否崩潰」
常見陷阱¶
-
Pool 滿時 silent drop 是最危險的,因為沒有任何 error log,資料遺失無法察覺
-
GDPR export 無上界在合規事件(如 GDPR 請求潮)下會同時觸發大量 goroutine
-
忽略 goroutine 追蹤導致 graceful shutdown SLA 無法保證(shutdown 看似完成但 goroutine 仍在跑)
最佳實踐¶
-
所有後台 goroutine 必須:(1) 加入 WaitGroup,(2) 有上界控制,(3) 失敗時顯式報錯
-
Graceful shutdown 需要明確的 goroutine drain 步驟(wg.Wait())
-
Semaphore 上界建議根據操作的資源消耗設定(GDPR export 建議 50,CPU 密集型更少)
相關概念¶
- go-concurrency-patterns----dangling-------dangling---
- go-graceful-shutdown----dangling-------dangling---
- production-readiness-audit----dangling-------dangling---
- Production Readiness Audit Methodology
相關視角¶
以下頁面與本概念共享主題,但從不同角度切入。保留獨立視角同時提供交叉參考:
- Release Gate Layering — 共享:
p0/ 獨特:go-live,production-readiness
來源 Sessions¶
| 日期 | Session | 貢獻摘要 |
|---|---|---|
| 2026-03-18 | 95c980e8-1c4d-4527-908a-2db6715a4bc9 | 從生產稽核中歸納了三種 fire-and-forget goroutine 反模式及其修復方案 |