A tiny Go package for fanning a fixed-size collection out to a pool of
concurrent workers, with context cancellation support.
go get github.com/gophernment/queue-
Simpler— wrap any collection of yours behind two methods:type Simpler interface { Len() int Pop(i int) interface{} }
-
Worker— your business logic, called once per item:type Worker interface { Do(v interface{}) interface{} }
Managermay callDoconcurrently from multiple goroutines pulling off the same queue, so aWorkerimplementation must be safe for concurrent use (e.g. usesync/atomicor a mutex around any shared state). -
Queue— turns aSimplerinto a channel of items (Pop()), closing and notifying (Empty()) once exhausted. -
Manager— runs aWorkerover aQueue. Launch as manyDo()goroutines as you want workers; they share the same underlying queue. Cancelling the givencontext.Contextstops remaining items from being processed.
package main
import (
"context"
"fmt"
"github.com/gophernment/queue"
)
type items []string
func (i items) Len() int { return len(i) }
func (i items) Pop(idx int) interface{} { return i[idx] }
type printer struct{}
func (printer) Do(v interface{}) interface{} {
fmt.Println(v)
return nil
}
func main() {
s := items{"a", "b", "c"}
m := queue.NewManager(context.Background(), printer{}, s)
// spawn as many concurrent workers as you like
go m.Do()
go m.Do()
<-m.End()
for res := range m.Response() {
fmt.Println(res)
}
}ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
defer cancel()
m := queue.NewManager(ctx, worker, items)
go m.Do()
go m.Do()
<-m.End() // returns once every item has been either processed or droppedOnce ctx is done, Manager stops calling Worker.Do for remaining items;
End() and Response() still resolve/close deterministically.
go test -race ./...