Go 並發編程提示詞(goroutine 泄漏排查、channel 用法、context 取消、errgroup 限制並發)
寫 Go 並發代碼(批量調用、生產者消費者、超時控制)或者服務 goroutine 數量持續上漲、偶發死鎖時用:讓 AI 審查或編寫並發代碼,確保每個 goroutine 都有退出路徑、channel 由誰關閉清楚、context 能逐層取消,並給出用 pprof 定位泄漏的方法。
通用大模型 對話模型通用
你是一名精通 Go 並發模型的後端工程師。請幫我處理下面的並發問題。 - 任務:[審查代碼/編寫代碼/排查泄漏] - Go 版本:[Go 版本](例:1.23) - 場景描述:[並發場景](例:並發調用 3 個下游接口,任一失敗就取消其餘) - 現象(排查時填寫):[現象](例:goroutine 數量每天漲幾萬) - 代碼: [粘貼代碼] 檢查與編寫時遵循這些原則,並逐條說明代碼是否滿足: 1. 每個啟動的 goroutine 都必須有明確的退出條件:誰負責通知它結束、在什麼情況下結束。 2. channel: - 由發送方關閉,接收方不關閉;多個發送方時用額外的同步手段確定關閉時機; - 無緩衝 channel 的發送在沒有接收者時會永久阻塞,這是最常見的泄漏原因(例如超時返回後,後台 goroutine 仍在嘗試發送結果); - 對 nil channel 讀寫會永久阻塞;向已關閉的 channel 發送會 panic。 3. context: - 從入口一路向下傳遞,不儲存在結構體中; - 所有可能阻塞的操作(網絡、等待 channel、sleep)都要和 context 的取消一起 select; - 用 WithTimeout 或 WithCancel 創建的 context,要調用返回的 cancel 釋放資源。 4. 並發上限:大批量任務不能無限制地啟動 goroutine,使用 errgroup 的並發限制或工作池;說明 errgroup 在第一個錯誤發生後如何取消其他任務。 5. 共享數據:用互斥鎖保護還是通過 channel 傳遞所有權;提醒用競態檢測運行測試。 6. panic:goroutine 內的 panic 不會被調用方的 recover 捕獲,需要時在 goroutine 內部處理。 排查泄漏時:給出用 pprof 查看 goroutine 堆棧的方法,教我從堆棧中找出「大量 goroutine 阻塞在同一行」的位置。 輸出:問題清單(位置 | 問題 | 後果)、修改後的完整代碼、對應的測試(包含競態檢測的運行命令)。
高亮處換成你自己的內容:[審查代碼/編寫代碼/排查泄漏]、[Go 版本]、[並發場景]、[現象]、[粘貼代碼]
ChatGPT Plus 充值
已被複製 0 次
使用說明
怎麼填變量:[現象] 排查泄漏時最好附上 pprof 的 goroutine 彙總(哪一行阻塞了多少個),AI 可以直接定位。審查代碼時把啟動 goroutine 的函數和它使用的 channel 定義一起貼上。
常見坑:
- 用 select 加超時實現「最多等 3 秒」,超時後函數返回了,但負責幹活的 goroutine 還在嘗試把結果發到無緩衝 channel 裏,永遠沒人接收,於是泄漏。給 channel 一個緩衝位,或者讓發送也監聽取消信號。
- 創建了帶超時的 context 卻沒有調用 cancel,定時器要等到超時才釋放。
- 每來一個請求啟動一個 goroutine 去處理一批子任務,沒有上限,高峰期內存暴漲。
追問技巧:追問「為這段代碼寫一個測試,在測試結束時檢查沒有遺留的 goroutine」,或「把這個模式改寫成可複用的工作池」。
示例輸出
示例,僅供參考(並發調用多個下游,任一失敗即取消其餘)
go
func FetchAll(ctx context.Context, ids []string) ([]Result, error) {
g, ctx := errgroup.WithContext(ctx) // 任一任務返回錯誤時,ctx 被取消
g.SetLimit(8) // 最多 8 個並發
results := make([]Result, len(ids)) // 每個 goroutine 寫自己的下標,無需加鎖
for i, id := range ids {
g.Go(func() error {
r, err := fetchOne(ctx, id) // fetchOne 內部必須響應 ctx 取消
if err != nil {
return fmt.Errorf("fetch %s: %w", id, err)
}
results[i] = r
return nil
})
}
if err := g.Wait(); err != nil {
return nil, err
}
return results, nil
}
說明:Go 1.22 起循環變量每次迭代都是新變量,閉包中直接使用 i、id 是安全的;更早的版本需要在循環內重新賦值。
bash
go test -race ./...同款作品
用這條提示詞做出來的作品;原作者會因此獲得積分
還沒有同款,來做第一個。


0 條評論
還沒有評論,來搶沙發~