gock

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 21, 2021 License: MIT Imports: 6 Imported by: 1

README

gock Go GoDoc

Package gock (a portmanteau of the go statement and "block") provides structured concurrency utilities for Go.

ctx, cancel := context.WithCancel(ctx)
things := make(chan Thing)

err := gock.Wait(func() error {
	defer close(things)
	return Produce(ctx, things)
}, func() error {
	defer cancel()
	return Consume(things)
})

// Both Produce and Consume are done here, and err is their combined errors.

Documentation

Overview

Package gock (a portmanteau of the "go" statement and "block") provides structured concurrency [1] utilities for Go.

[1] https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddConcurrentError

func AddConcurrentError(to error, err error) error

AddConcurrentError merges two concurrent, possibly nil errors.

If both are nil, nil is returned.

If both are equal, ie. the same error value has been passed twice, that error is returned.

If only one of the two is non-nil, that one is returned.

If both are non-nil, a ConcurrentErrors is returned with both. If any of them is itself a ConcurrentErrors, the resulting ConcurrentErrors is flattened, ie. it incorporates the errors contained in the merged ConcurrentErrors, not the ConcurrentErrors themselves.

func AnyAs

func AnyAs(err error, target interface{}) bool

AnyAs runs errors.As on the concurrent errors bundled in err until one matches.

func AnyIs

func AnyIs(err, target error) bool

AnyIs returns whether any of the concurrent errors bundlded in err is the given error, as defined by errors.Is.

func Wait

func Wait(fs ...func() error) error

Wait runs the provided functions concurrently. It waits for all of them to return before returning itself.

It returns the result of repeatedly calling AddConcurrentError on each error returned by the function.

If any of the functions panics in another goroutine, the recovered value is repanicked in the goroutine that calls Wait, wrapped in an error type that keeps the original stack trace where the panic happened and that has the method Unwrap() error to recover the original value, if it was an error.

Example (CommonErrorAncestor)
package main

import (
	"errors"
	"fmt"

	"github.com/tcard/gock"
)

func main() {
	var ErrCommonAncestor = errors.New("ye eldest")

	err := gock.Wait(func() error {
		return fmt.Errorf(
			"first in first chain: %w",
			fmt.Errorf(
				"second in first chain: %w",
				ErrCommonAncestor,
			),
		)
	}, func() error {
		return nil
	}, func() error {
		return fmt.Errorf(
			"first in second chain: %w",
			ErrCommonAncestor,
		)
	})

	fmt.Println(errors.Is(err, ErrCommonAncestor))
}
Output:

true
Example (ConcurrentErrors)
package main

import (
	"errors"
	"fmt"

	"github.com/tcard/gock"
)

func main() {
	var ErrOops = errors.New("oops")
	var ErrFailed = errors.New("failed")

	err := gock.Wait(func() error {
		return ErrFailed
	}, func() error {
		return ErrOops
	})

	fmt.Println(gock.AnyIs(err, ErrOops))
	fmt.Println(gock.AnyIs(err, ErrFailed))
}
Output:

true
true
Example (SameErrorTwice)
package main

import (
	"errors"
	"fmt"

	"github.com/tcard/gock"
)

func main() {
	var ErrOops = errors.New("oops")

	err := gock.Wait(func() error {
		return ErrOops
	}, func() error {
		return nil
	}, func() error {
		return ErrOops
	})

	fmt.Println(err == ErrOops)
}
Output:

true
Example (SingleError)
package main

import (
	"errors"
	"fmt"

	"github.com/tcard/gock"
)

func main() {
	var ErrOops = errors.New("oops")

	err := gock.Wait(func() error {
		return nil
	}, func() error {
		return ErrOops
	})

	fmt.Println(err == ErrOops)
}
Output:

true

Types

type ConcurrentErrors

type ConcurrentErrors struct {
	Errors []error
}

ConcurrentErrors aggregates multiple errors that happened concurrently but were then aggreegated with AddConcurrentError.

Its Unwrap method returns, if it exists, the common ancestor among the chains of all errors.

Use AddConcurrentError to construct it, which keeps the invariant that a ConcurrentErrors doesn't contain other ConcurrentErrors.

func (ConcurrentErrors) Error

func (errs ConcurrentErrors) Error() string

Error implements error for ConcurrentErrors.

func (ConcurrentErrors) Is added in v0.1.6

func (errs ConcurrentErrors) Is(err error) bool

Is returns true if errors.Is(subError, err) returns true for all errors inside the ConcurrentErrors.

func (ConcurrentErrors) Unwrap

func (errs ConcurrentErrors) Unwrap() error

Unwrap returns, if it exists, the common ancestor among the error chains of all errors contained in the ConcurrentErrors.

type GoFunc added in v0.1.4

type GoFunc func(func() error)

A GoFunc runs a given function concurrently.

func Bundle

func Bundle() (g GoFunc, wait func() error)

Bundle returns a function g to run functions concurrently, and a function wait to wait for all the functions provided to g to return before returning itself. Thus, the provided functions run in a "bundle" of concurrent goroutines.

wait returns the result of repeatedly calling AddConcurrentError on each error returned by the function.

It is safe to call g or wait concurrently from different goroutines.

Once wait returns, calling g again panics. Calling wait more than once just returns the same result.

If any of the functions panics in another goroutine, the recovered value is repanicked in the goroutine that calls wait, wrapped in an error type that keeps the original stack trace where the panic happened and that has the method Unwrap() error to recover the original value, if it was an error.

You may prefer Wait, which is a shortcut.

func (GoFunc) NoErr added in v0.1.4

func (g GoFunc) NoErr(f func())

NoErr makes the GoFunc run a function that doesn't return an error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL