這可能是我最後一次在 Go 中進行錯誤處理。我認為這也是最好的。我們知道我們執行的每條指令都在上下文中。並且上下文可能有錯誤。這時我想為什麼不簡單地在當前上下文之上創建一個包裝器。因此,如果透過特定 fn 執行所有任務,那麼我們可以檢查 ctx 是否有錯誤,如果有錯誤,則不執行,否則執行並收集錯誤。這可能會成為一種反模式,但在它成為之前,我們可以嘗試一下。
好吧,遊標有一些東西要加 ->
問題
處理併發任務時請考慮以下常見挑戰:
- 從多個 goroutine 收集錯誤
- 維護線程安全
- 限制並發執行
- 收集所有錯誤的同時保留第一個錯誤
- 乾淨的錯誤處理模式
解決方案:TaskContext
讓我們建立一個 TaskContext 來解決這些問題:
package taskctx import ( "context" "errors" "fmt" "sync" ) type RunFn[T any] func() (T, error) type TaskContext struct { context.Context mu sync.RWMutex err error multiErr []error } func NewTaskContext(parent context.Context) *TaskContext { if parent == nil { panic("cannot create context from nil parent") } return &TaskContext{Context: parent} }
主要特點
1. 線程安全的錯誤處理
func (c *TaskContext) WithError(err error) *TaskContext { if err == nil { return c } c.mu.Lock() defer c.mu.Unlock() c.multiErr = append(c.multiErr, err) if c.err == nil { c.err = err } else { c.err = errors.Join(c.err, err) } return c }
2. 單任務執行
func Run[T any](ctx *TaskContext, fn RunFn[T]) T { var zero T if err := ctx.Err(); err != nil { return zero } result, err := fn() if err != nil { ctx.WithError(err) return zero } return result }
3. 並行任務執行
func RunParallel[T any](ctx *TaskContext, fns ...func() (T, error)) ([]T, error) { if err := ctx.Err(); err != nil { return nil, err } results := make([]T, len(fns)) var resultsMu sync.Mutex var wg sync.WaitGroup wg.Add(len(fns)) for i, fn := range fns { i, fn := i, fn go func() { defer wg.Done() result, err := fn() if err != nil { ctx.AddError(fmt.Errorf("task %d: %w", i+1, err)) } else { resultsMu.Lock() results[i] = result resultsMu.Unlock() } }() } wg.Wait() return results, ctx.Errors() }
4. 受控並發
func RunParallelWithLimit[T any](ctx *TaskContext, limit int, fns ...func() (T, error)) ([]T, error) { // ... similar to RunParallel but with semaphore ... sem := make(chan struct{}, limit) // ... implementation ... }
使用範例
簡單的任務執行
func ExampleTaskContext_ShipmentProcessing() { ctx := goctx.NewTaskContext(context.Background()) order := dummyOrder() shipment := dummyShipment() // Step 1: Validate address // Step 2: Calculate shipping cost // Step 3: Generate label _ = goctx.Run(ctx, validateAddress("123 Main St")) cost := goctx.Run(ctx, calculateShipping(order)) trackingNum := goctx.Run(ctx, generateLabel(shipment.OrderID, cost)) if ctx.Err() != nil { fmt.Printf("Error: %v\n", ctx.Err()) return } shipment.Status = "READY" shipment.TrackingNum = trackingNum fmt.Printf("Shipment processed: %+v\n", shipment) // Output: // Shipment processed: {OrderID:ORD123 Status:READY TrackingNum:TRACK-ORD123-1234567890} }
平行任務執行
func ExampleTaskContext_OrderProcessing() { ctx := goctx.NewTaskContext(context.Background()) // Mock order order := []OrderItem{ {ProductID: "LAPTOP", Quantity: 2}, {ProductID: "MOUSE", Quantity: 3}, } taskCtx := goctx.NewTaskContext(ctx) // Create inventory checks for each item inventoryChecks := goctx.Run[[]goctx.RunFn[bool]](taskCtx, func() ([]goctx.RunFn[bool], error) { return streams.NewTransformer[OrderItem, goctx.RunFn[bool]](order). Transform(streams.MapItSimple(checkInventory)). Result() }) // Run inventory checks in parallel _, err := goctx.RunParallel(ctx, inventoryChecks...) fmt.Printf("Inventory check error: %v\n", err) // Output: // Inventory check error: task 1: insufficient inventory for LAPTOP }
好處
- 執行緒安全性:所有操作都受到互斥鎖的保護
- 錯誤集合:維護第一個錯誤和所有錯誤
- 上下文整合:與Go的上下文套件一起使用
- 通用支援:適用於任何回傳類型
- 並發控制:限制並行執行的內建支援
測試
以下是測試實作的方法:
func TestTaskContext(t *testing.T) { t.Run("handles parallel errors", func(t *testing.T) { ctx := NewTaskContext(context.Background()) _, err := RunParallel(ctx, func() (int, error) { return 0, errors.New("error 1") }, func() (int, error) { return 0, errors.New("error 2") }, ) assert.Error(t, err) assert.Contains(t, err.Error(), "error 1") assert.Contains(t, err.Error(), "error 2") }) }
結論
這個 TaskContext 實作提供了一個強大的解決方案,可以在 Go 中透過正確的錯誤處理來處理並發任務執行。當您需要執行以下操作時,它特別有用:
- 同時執行多個任務
- 收集所有任務的錯誤
- 限制並發執行
- 維護線程安全
- 收集所有錯誤的同時追蹤第一個錯誤
完整程式碼可在 GitHub 上取得。
資源
- Go 上下文包
- Go 並發模式
- Go 中的錯誤處理
您使用什麼模式來處理 Go 中的並發任務執行?在下面的評論中分享你的想法!
- https://x.com/mahadev_k_
- https://in.linkedin.com/in/mahadev-k-934520223
以上是在 Go 中建立健全的任務執行上下文的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文解釋了GO的軟件包導入機制:命名imports(例如導入“ fmt”)和空白導入(例如導入_ fmt; fmt;)。 命名導入使包裝內容可訪問,而空白導入僅執行t

本文詳細介紹了MySQL查詢結果的有效轉換為GO結構切片。 它強調使用數據庫/SQL的掃描方法來最佳性能,避免手動解析。 使用DB標籤和Robus的結構現場映射的最佳實踐

本文解釋了Beego的NewFlash()函數,用於Web應用程序中的頁間數據傳輸。 它專注於使用newflash()在控制器之間顯示臨時消息(成功,錯誤,警告),並利用會話機制。 Lima

本文演示了創建模擬和存根進行單元測試。 它強調使用接口,提供模擬實現的示例,並討論最佳實踐,例如保持模擬集中並使用斷言庫。 文章

本文探討了GO的仿製藥自定義類型約束。 它詳細介紹了界面如何定義通用功能的最低類型要求,從而改善了類型的安全性和代碼可重複使用性。 本文還討論了局限性和最佳實踐

本文詳細介紹了在GO中詳細介紹有效的文件,將OS.WriteFile(適用於小文件)與OS.openfile和緩衝寫入(最佳大型文件)進行比較。 它強調了使用延遲並檢查特定錯誤的可靠錯誤處理。

本文使用跟踪工具探討了GO應用程序執行流。 它討論了手冊和自動儀器技術,比較諸如Jaeger,Zipkin和Opentelemetry之類的工具,並突出顯示有效的數據可視化


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3漢化版
中文版,非常好用

記事本++7.3.1
好用且免費的程式碼編輯器

Dreamweaver Mac版
視覺化網頁開發工具