collections

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package collections runs a function over a slice concurrently — the Go analogue of Array.map followed by Promise.all, or the p-map / p-queue libraries from npm.

// JS: const users = await pMap(ids, getUser, { concurrency: 10 });
users, err := collections.Map(ids, getUser, collections.Concurrency(10))

Map and ForEach map an "async function" (one returning *github.com/burrows99/async/promise.Promise) over a slice, optionally bounding how many run at once with Concurrency. Queue is a reusable work queue with the same bound (npm's p-queue). All of them are fail-fast like Promise.all: the first error stops new work from starting and is returned, while in-flight work — which Go, like JavaScript, cannot preempt — runs to completion.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ForEach

func ForEach[T, U any](items []T, fn func(T) *promise.Promise[U], opts ...Option) error

ForEach runs fn over every item concurrently for its side effects, discarding the results — the analogue of `await Promise.all(items.map(fn))` when you do not need the values. It honours Concurrency and is fail-fast like Map.

func Map

func Map[T, U any](items []T, fn func(T) *promise.Promise[U], opts ...Option) ([]U, error)

Map runs fn over every item concurrently and returns the results in input order — the analogue of `await Promise.all(items.map(fn))`, or of pMap when combined with Concurrency.

fn is an "async function": it returns a *promise.Promise. With Concurrency, at most n promises are started at a time; without it, all start at once. Map is fail-fast like Promise.all: on the first error it stops starting new work and returns a nil slice with that error. In-flight work that ignores its signal runs to completion, exactly as it would in JavaScript.

Example

The JavaScript this mirrors:

const doubled = await Promise.all(ids.map(double));
package main

import (
	"fmt"

	"github.com/burrows99/async/collections"
	"github.com/burrows99/async/promise"
)

// double is an "async function": doubling id, returned as a Promise.
func double(id int) *promise.Promise[int] {
	return promise.New(func() (int, error) {
		return id * 2, nil
	})
}

func main() {
	doubled, err := collections.Map([]int{1, 2, 3, 4}, double)
	fmt.Println(doubled, err)
}
Output:
[2 4 6 8] <nil>
Example (Concurrency)

The JavaScript this mirrors:

const doubled = await pMap(ids, double, { concurrency: 2 });
package main

import (
	"fmt"

	"github.com/burrows99/async/collections"
	"github.com/burrows99/async/promise"
)

// double is an "async function": doubling id, returned as a Promise.
func double(id int) *promise.Promise[int] {
	return promise.New(func() (int, error) {
		return id * 2, nil
	})
}

func main() {
	doubled, err := collections.Map([]int{1, 2, 3, 4}, double, collections.Concurrency(2))
	fmt.Println(doubled, err)
}
Output:
[2 4 6 8] <nil>

Types

type Option

type Option func(*config)

Option configures Map, ForEach, and NewQueue.

func Concurrency

func Concurrency(n int) Option

Concurrency bounds how many tasks run at once — the analogue of the { concurrency: n } option in p-map and p-queue. A value of zero or less means unbounded. It applies to Map, ForEach, and NewQueue.

type Queue

type Queue[T any] struct {
	// contains filtered or unexported fields
}

Queue is a reusable, concurrency-limited work queue — the analogue of npm's p-queue (PQueue). Create one with NewQueue, hand it work with Queue.Add, and wait for everything to finish with Queue.OnIdle.

Unlike Map, a Queue has no fixed set of items: add tasks over time, each returning its own promise.Promise. At most the configured number run concurrently; the rest wait their turn.

Example

The JavaScript this mirrors:

const queue = new PQueue({ concurrency: 2 });
jobs.forEach(j => queue.add(() => run(j)));
await queue.onIdle();
package main

import (
	"fmt"
	"sort"

	"github.com/burrows99/async/collections"
	"github.com/burrows99/async/promise"
)

func main() {
	queue := collections.NewQueue[int](2)
	ps := make([]*promise.Promise[int], 3)
	for i := range ps {
		n := i + 1
		ps[i] = queue.Add(func() (int, error) { return n * n, nil })
	}
	queue.OnIdle()

	squares := make([]int, 0, len(ps))
	for _, p := range ps {
		v, _ := p.Await()
		squares = append(squares, v)
	}
	sort.Ints(squares)
	fmt.Println(squares)
}
Output:
[1 4 9]

func NewQueue

func NewQueue[T any](concurrency int, opts ...Option) *Queue[T]

NewQueue returns a Queue that runs at most concurrency tasks at once — the analogue of `new PQueue({ concurrency })`. A value of zero or less is treated as 1. A Concurrency option, if supplied, overrides the argument.

func (*Queue[T]) Add

func (q *Queue[T]) Add(fn func() (T, error)) *promise.Promise[T]

Add schedules fn on the queue and returns a promise.Promise for its result — the analogue of p-queue's queue.add(fn). The task waits for a free slot before running, so no more than the queue's concurrency run at once. The returned Promise settles like any other: Await it for the result, and a panic in fn becomes a *promise.PanicError.

func (*Queue[T]) OnIdle

func (q *Queue[T]) OnIdle()

OnIdle blocks until every task added so far has finished — the analogue of `await queue.onIdle()`. Adding more work after OnIdle returns is allowed; OnIdle simply waits for whatever has been added up to that point.

Jump to

Keyboard shortcuts

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