有一个程序失败用同步的errgroup取消所有的父子goroutines

180 阅读1分钟

我们有2个主/父goroutines,每个有5个子/子goroutines。我们总共有10个goroutine。我们要做的是,如果其中任何一个失败,所有的都会失败。我们将通过返回一个错误来做到这一点。我们使用的例子就像在玩游戏。我们将在每个子/子goroutine中随机挑选两个数字。如果这两个数字都等于0,那么我们将使这个goroutine失败。否则,所有的程序将永远运行下去。

MAIN/PARENT - SUB/CHILD
1             1, 2, 3, 4, 5
2             1, 2, 3, 4, 5

例子

package main

import (
	"context"
	"fmt"
	"math/rand"
	"time"

	"golang.org/x/sync/errgroup"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func random(min, max int) int {
	if min == 0 {
		max = max + 1
	}

	return rand.Intn(max) + min
}

func main() {
	eg, ctx := errgroup.WithContext(context.Background())

	for i := 1; i <= 2; i++ {
		i := i

		eg.Go(func() error {
			return child(ctx, eg, i)
		})
	}

	if err := eg.Wait(); err != nil {
		fmt.Println(err)
	}
}

func child(ctx context.Context, eg *errgroup.Group, id int) error {
	for i := 1; i <= 5; i++ {
		i := i

		eg.Go(func() error {
			for ctx.Err() == nil {
				a, b := random(0, 3), random(0, 3)

				if a == 0 && b == 0 {
					return fmt.Errorf("MIAN:%d - CHILD:%d => (%d-%d)\n", id, i, a, b)
				}

				// Do the work
				fmt.Printf("MIAN:%d - CHILD:%d => (%d-%d)\n", id, i, a, b)
			}

			return nil
		})
	}

	return nil
}

测试

MIAN:1 - SUB:1 => (0-3)
MIAN:1 - SUB:1 => (1-0)
MIAN:1 - SUB:2 => (0-2)
MIAN:2 - SUB:1 => (1-2)
MIAN:2 - SUB:2 => (3-2)
MIAN:1 - SUB:1 => (0-0)
MIAN:1 - SUB:1 => (0-2)
MIAN:1 - SUB:4 => (1-3)
MIAN:1 - SUB:1 => (3-3)
MIAN:1 - SUB:1 => (0-0)
MIAN:2 - SUB:2 => (2-2)
MIAN:2 - SUB:1 => (2-3)
MIAN:1 - SUB:2 => (3-3)
MIAN:1 - SUB:3 => (0-0)
MIAN:1 - SUB:1 => (3-2)
MIAN:2 - SUB:1 => (0-0)