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>
歡迎關注我的微信公眾號: