Documentation
¶
Overview ¶
Package errgroup golang.org/x/sync/errgroup.Group, providing both backwards compatibility, but also introducing new, safer APIs.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type ContextGroup ¶
type ContextGroup interface {
// Go calls the given function in a new goroutine, passing the group context.
//
// The first call to return a non-nil error cancels the group's context.
// The error will be returned by Wait().
//
// Go returns immediately if the group context is already cancelled.
Go(func(context.Context) error)
// Wait blocks until all function calls from the Go method have returned, then
// returns the first non-nil error (if any) from them.
Wait() error
// TryGo calls the given function in a new goroutine only if the number of
// active goroutines in the group is currently below the configured limit.
//
// The return value reports whether the goroutine was started.
// TryGo returns true immediately if the group context is already cancelled.
TryGo(func(context.Context) error) bool
}
ContextGroup is a variant of golang.org/x/sync/errgroup.Group that: - automatically catches panics - forces the correct context - manages the context lifetime - early-exits any calls to Go() or TryGo() once the context is canceled
Unlike the golang version, ContextGroup cannot be reused after Wait() has been called, because the context is dead and no new go funcs will be run.
func New ¶
func New(ctx context.Context) ContextGroup
New returns a new ContextGroup derived from ctx.
All funcs passed into [ContextGroup.Go] are wrapped with panic handlers and receive the group context automatically.
Example (JustErrors) ¶
JustErrors illustrates the use of a Group in place of a sync.WaitGroup to simplify goroutine counting and error handling. This example is derived from the sync.WaitGroup example at https://golang.org/pkg/sync/#example_WaitGroup.
package main
import (
"context"
"fmt"
"net/http"
"github.com/fullstorydev/go/errgroup"
)
func main() {
g := errgroup.New(context.Background())
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
}
for _, url := range urls {
// Launch a goroutine to fetch the URL.
url := url // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func(ctx context.Context) error {
// Fetch the URL.
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err == nil {
_ = resp.Body.Close()
}
return err
})
}
// Wait for all HTTP fetches to complete.
if err := g.Wait(); err == nil {
fmt.Println("Successfully fetched all URLs.")
}
}
Output: Successfully fetched all URLs.
Example (Parallel) ¶
Parallel illustrates the use of a Group for synchronizing a simple parallel task: the "Google Search 2.0" function from https://talks.golang.org/2012/concurrency.slide#46, augmented with a Context and error-handling.
Google := func(ctx context.Context, query string) ([]Result, error) {
g := errgroup.New(ctx)
searches := []Search{Web, Image, Video}
results := make([]Result, len(searches))
for i, search := range searches {
i, search := i, search // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func(ctx context.Context) error {
result, err := search(ctx, query)
if err == nil {
results[i] = result
}
return err
})
}
if err := g.Wait(); err != nil {
return nil, err
}
return results, nil
}
results, err := Google(context.Background(), "golang")
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
return
}
for _, result := range results {
fmt.Println(result)
}
Output: web result for "golang" image result for "golang" video result for "golang"
type ErrGroup ¶
type ErrGroup interface {
// Go calls the given function in a new goroutine, passing the group context.
//
// The first call to return a non-nil error cancels the group's context.
// The error will be returned by Wait.
Go(func() error)
// Wait blocks until all function calls from the Go method have returned, then
// returns the first non-nil error (if any) from them.
Wait() error
// TryGo calls the given function in a new goroutine only if the number of
// active goroutines in the group is currently below the configured limit.
//
// The return value reports whether the goroutine was started.
TryGo(func() error) bool
// SetLimit limits the number of active goroutines in this group to at most n.
// A negative value indicates no limit.
//
// Any subsequent call to the Go method will block until it can add an active
// goroutine without exceeding the configured limit.
//
// The limit must not be modified while any goroutines in the group are active.
SetLimit(n int)
}
ErrGroup defines a compatibility interface between Group and golang.org/x/sync/errgroup.Group.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group is a drop-in replacement for golang.org/x/sync/errgroup.Group that automatically catches panics. Provided for backwards compatibility; prefer New() ContextGroup instead.
Example (JustErrors) ¶
JustErrors illustrates the use of a Group in place of a sync.WaitGroup to simplify goroutine counting and error handling. This example is derived from the sync.WaitGroup example at https://golang.org/pkg/sync/#example_WaitGroup.
package main
import (
"fmt"
"net/http"
"github.com/fullstorydev/go/errgroup"
)
func main() {
g := new(errgroup.Group)
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
}
for _, url := range urls {
// Launch a goroutine to fetch the URL.
url := url // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func() error {
// Fetch the URL.
resp, err := http.Get(url)
if err == nil {
_ = resp.Body.Close()
}
return err
})
}
// Wait for all HTTP fetches to complete.
if err := g.Wait(); err == nil {
fmt.Println("Successfully fetched all URLs.")
}
}
Output: Successfully fetched all URLs.
Example (Parallel) ¶
Parallel illustrates the use of a Group for synchronizing a simple parallel task: the "Google Search 2.0" function from https://talks.golang.org/2012/concurrency.slide#46, augmented with a Context and error-handling.
package main
import (
"context"
"fmt"
"os"
"github.com/fullstorydev/go/errgroup"
)
var (
Web = fakeSearch("web")
Image = fakeSearch("image")
Video = fakeSearch("video")
)
type Result string
type Search func(ctx context.Context, query string) (Result, error)
func fakeSearch(kind string) Search {
return func(_ context.Context, query string) (Result, error) {
return Result(fmt.Sprintf("%s result for %q", kind, query)), nil
}
}
func main() {
Google := func(ctx context.Context, query string) ([]Result, error) {
g, ctx := errgroup.WithContext(ctx)
searches := []Search{Web, Image, Video}
results := make([]Result, len(searches))
for i, search := range searches {
i, search := i, search // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func() error {
result, err := search(ctx, query)
if err == nil {
results[i] = result
}
return err
})
}
if err := g.Wait(); err != nil {
return nil, err
}
return results, nil
}
results, err := Google(context.Background(), "golang")
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
return
}
for _, result := range results {
fmt.Println(result)
}
}
Output: web result for "golang" image result for "golang" video result for "golang"
func WithContext ¶
WithContext returns a new Group derived from ctx.
All funcs passed into Group.Go are wrapped with panic handlers.
func (*Group) Go ¶
Go calls the given function in a new goroutine, passing the group context.
The first call to return a non-nil error cancels the group's context. The error will be returned by Wait.
func (*Group) SetLimit ¶
SetLimit limits the number of active goroutines in this group to at most n. A negative value indicates no limit.
Any subsequent call to the Go method will block until it can add an active goroutine without exceeding the configured limit.
The limit must not be modified while any goroutines in the group are active.
type PanicError ¶
type PanicError struct {
// contains filtered or unexported fields
}
PanicError represents a wrapped recovered panic value.
func NewPanicError ¶
func NewPanicError(recovered any) *PanicError
NewPanicError creates a new PanicError with the given recovered panic value. The caller stack frames are captured and attached, starting with the caller of NewPanicError.
func NewPanicErrorCallers ¶
func NewPanicErrorCallers(recovered any, skip int) *PanicError
NewPanicErrorCallers creates a new PanicError with the given recovered panic value.
The argument skip is the number of stack frames to skip before recording in pc, with 0 identifying the frame for NewPanicErrorCallers itself and 1 identifying the caller of NewPanicErrorCallers.
func (*PanicError) Error ¶
func (e *PanicError) Error() string
func (*PanicError) Format ¶
func (e *PanicError) Format(s fmt.State, verb rune)
Format implements the fmt.Formatter interface to support rich formatting for %+v and %#v.
func (*PanicError) Recovered ¶
func (e *PanicError) Recovered() any
Recovered returns the original value.
func (*PanicError) StackFrames ¶
func (e *PanicError) StackFrames() []uintptr
StackFrames returns a slice of program counters composing this error's stacktrace.
func (*PanicError) StackTrace ¶
func (e *PanicError) StackTrace() string
StackTrace returns the originally captured stack trace as a multiline string.
func (*PanicError) Unwrap ¶
func (e *PanicError) Unwrap() error
Unwrap returns the recovered value if it is itself an error, otherwise returns nil.