Goroutine 與 Context 生命週期
核心原則:每個被 spawn 的 goroutine 都必須有明確的結束路徑(exit path),通常透過 context 的 cancel 來控制。否則在 app graceful shutdown 時,這些 goroutine 可能卡住程序,造成 goroutine leak。
為什麼會漏?
HTTP handler 常會「先回應用戶、背景再做事」(例如 enqueue SQS)。這時容易犯兩個錯:
- 直接用 request context:request 一結束就 cancel,背景工作可能被提早掐掉。
- 用
context.WithoutCancel(c)完全 detach:背景工作活下來了,但 app shutdown 時也收不到取消信號,變成沒有 exit path。
正確做法是:背景工作綁 app-level context(隨程序關閉而 cancel),同時可保留 request 的 logger fields(如 request_id)。