巧妙的使用WaitGroup處理錯誤


1. 寫在前面

微信公眾號:[double12gzh]

個人主頁: https://gzh.readthedocs.io

關注容器技術、關注Kubernetes。問題或建議,請公眾號留言。

使用Go的眾多好處之一是它在並發方面十分簡單,而大家比熟悉的WaitGroups就是一個很好的例子。雖然在並發處理上十分的方便,但要想有效地處理並發和錯誤可能很棘手。

本篇文章旨在概述如何在不停止程序執行的情況下,運行多個goroutine並有效處理任何錯誤。

2. 具體實現

對於這個如何上,可以簡單的概括為以下三點:

  • 兩個channel。這兩個channel的作用是用於傳遞錯誤傳遞WaitGroup何時完成
  • 一個groutine。主要作用是用於監聽WaitGroup是否完成,如果完成了,將會關閉某個channel。
  • 一個Select。它用於監聽出現的錯誤或WaitGroup完成與否,無論誰先結束,那么Select就會先執行誰。

具體代碼如下:

package main

import (
	"errors"
	"fmt"
	"sync"
)

// ErrorHandler 返回一個錯誤。
func ErrorHandler() error {
	return errors.New("generated errors")
}

func main() {
	// 創建兩個channel,一個用於傳遞錯誤,另一個表示WaitGroup是否結束。
	errCh := make(chan error)
	wgCh := make(chan bool)

	var wg sync.WaitGroup

	wg.Add(2)

	go func() {
		fmt.Println("WaitGroup 1st.")

		// 這里可以定義我們需要執行的操作

		wg.Done()
	}()

	go func() {
		fmt.Println("WaitGroup 2nd")

		// 返回自定義的錯誤
		if err := ErrorHandler(); err != nil {
			errCh <- err
		}

		wg.Done()
	}()

	go func() {
		wg.Wait()
		close(wgCh)
	}()

	// 當有錯誤返回或WaitGroup執行結束時會被執行。
	select {
	case <-wgCh:
		break
	case err := <-errCh:
		close(errCh)
		panic(err)
	}

	fmt.Println("Main func ended!")
}

運行上述代碼,我們可以得到以下的輸出,也從而能驗證我們已經基於此達到了我們的目的。

PS C:\Users\jeffrey\Desktop\hello> go run main.go
WaitGroup 1st.
WaitGroup 2nd
panic: generated errors.

goroutine 1 [running]:
main.main()
        C:/Users/jeffrey/Desktop/hello/main.go:53 +0x2a6
exit status 2
PS C:\Users\jeffrey\Desktop\hello> 

歡迎關注我的微信公眾號:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM