跳轉到

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()
問題:graceful shutdown 時 audit 記錄可能遺失。

2. GDPR Export — 無 Semaphore 上界

// 反模式:每個請求無限制啟動 goroutine
go func() { exportUserData(userID) }()

// 修復:加 semaphore 上界(建議 50)
sem <- struct{}{}
go func() {
    defer func() { <-sem }()
    exportUserData(userID)
}()
問題:可同時啟動數千 goroutine,記憶體耗盡。

3. Dungeon S3 Upload — Pool 滿時 Silent Drop

// 反模式:pool 滿時靜默丟棄任務
select {
case pool <- task:
default: // 靜默丟棄
}

// 修復:pool 滿時 fail-fast(返回 error,讓上層決策)
select {
case pool <- task:
default:
    return ErrPoolFull
}
問題:S3 上傳失敗無任何錯誤回饋,資料悄悄遺失。

判斷標準(何時是 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

相關視角

以下頁面與本概念共享主題,但從不同角度切入。保留獨立視角同時提供交叉參考:

來源 Sessions

日期 Session 貢獻摘要

| 2026-03-18 | 95c980e8-1c4d-4527-908a-2db6715a4bc9 | 從生產稽核中歸納了三種 fire-and-forget goroutine 反模式及其修復方案 |


本概念頁面由 Semi-Brain Wiki 系統自動維護

最後更新: 2026-03-18