巧妙的使用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> 
欢迎关注我的微信公众号:


 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号