[Go] errgroupの使い方

goroutineで複数のタスクを平行して実行し、結果を待合せたい場合にsync.WaitGroupを使ってきた。

このような処理の場合、実行したタスクのどれかが失敗した場合は処理全体を失敗したものとして扱いたい。そんな場合に便利なパッケージを知ったのでメモ。

複数の文字列をもらって出力するだけのタスクで使ってみると以下のような感じ。errgroupのGoメソッドでタスクを平行起動しつつ、完了をWaitメソッドで待合せる。

package main
import (
	"errors"
	"fmt"
	"time"
	"golang.org/x/sync/errgroup"
)
func main() {
	// メッセージの内容を出力するタスク
	messages := []string{"first", "second", "third"}
	var g errgroup.Group
	for _, message := range messages {
		message := message
		g.Go(func() error {
			time.Sleep(2 * time.Second)
			if message == "three" {
				return errors.New("error")
			}
			fmt.Printf("message=%s\n", message)
			return nil
		})
	}
	// タスクの完了を待合せる
	// いずれかのタスクでエラーになると、err != nil になる
	if err := g.Wait(); err == nil {
		fmt.Printf("tasks finished successfully\n")
	} else {
		fmt.Printf("some task failed\n")
	}
}

実行すると出力は以下のようになる。"three"の表示時にエラーとなるため、処理全体の結果もエラーとなっている。

$ go run main.go
message=one
message=two
some task failed


タスク内の文字列比較を"three"→"3"に変更してエラーにならないようにしてから、再度実行すると以下の通り。処理全体が成功している。

$ go run main.go
message=two
message=one
message=three
tasks finished successfully


非常に簡単に並行タスクの待合せを書けます。


この記事が気に入ったらサポートをしてみませんか?