在日常生活中我们经常会涉及到这样一个场景:给一批任务,需要快速完成。
遇到这种场景的话,大家一般都会想到直接用多线程来实现,首先把这一批任务给分解成多个任务,然后放到子线程里面去执行即可。在go语言中主要使用WaitGroup即可。
但是试想一下,这一批任务得多复杂,分工下去之后总会出现部分任务执行失败的情况,如果有任务失败,我们则认为整批任务都是失败饿,不算全完成了。在go语言中WaitGroup仅能执行代码,但是没法对错误信息进行收集和返回,所以我们没法直观的了解到是否有子任务是全部执行完成的。在go语言中为了拓展这样的场景需求,因此新增了errgroup库来实现这里的需求。下面我们来介绍下errgroup库的相关使用:
一、多线程子任务出错后返回错误信息
errgroup库实现了WaitGroup的所有功能,同时拓展了错误的信息返回。同时在编码层面,errgroup也比WaitGroup看起来直观很多,下面我们来演示下返回错误信息,示例代码如下:
package main import ( "errors" "fmt" "golang.org/x/sync/errgroup" "strconv" ) func main() { var nos = []string{ "1", "2", "3", } g := new(errgroup.Group) for _, no := range nos { num, err := strconv.Atoi(no) if err != nil { panic(err) } g.Go(func() error { if num%2 != 0 { err := errors.New(fmt.Sprintf("%d 不是双数", num)) return err } return nil }) } if err := g.Wait(); err != nil { fmt.Println(err) } else { fmt.Println("全部执行成功!") } }
上面的案例是给每个子线程一个数字,如果不是双数就报错。运行下:
可以看到这里直接返回了错误,我们就可以判断出这批任务是没有全部执行成功的。是不是很实用?
备注:
1、在最后的err信息输出的时候,errgroup是随机返回的一条错误信息,不是返回全部信息,也不是固定返回哪一个线程的错误信息,是随机的,并且只有一条。
二、设置并发数
虽然WaitGroup也可以设置并发数,但是errgroup设置并发数对于我们编码来说更加的直观。示例代码如下:
package main import ( "errors" "fmt" "golang.org/x/sync/errgroup" "strconv" ) func main() { var nos = []string{ "1", "2", "3", } g := new(errgroup.Group) g.SetLimit(2) for _, no := range nos { num, err := strconv.Atoi(no) if err != nil { panic(err) } g.Go(func() error { if num%2 != 0 { err := errors.New(fmt.Sprintf("%d 不是双数", num)) return err } return nil }) } if err := g.Wait(); err != nil { fmt.Println(err) } else { fmt.Println("全部执行成功!") } }
上面的示例我们仅是新增了一行代码:
g.SetLimit(2)
代表可同时并发执行的任务数是2。这样子就直接控制了并发数了,对于编码来说是不是非常简单?
以上就是errgroup的用法,建议大家在编写多线程项目的时候可以尝试下。
还没有评论,来说两句吧...