Collections Go is a library that provides a set of collections for Go. It provides methods to manipulate collections.
A sequence is a collection that has an order. The sequence interface is defined as follows:
package contracts
type Sequence[T any] interface {
ToSlice() []T
Each(f ApplyFunc[T]) error
Where(f UnaryPredicate[T]) (Sequence[T], error)
WhereMust(f UnaryPredicateMust[T]) Sequence[T]
FirstWhereMust(predicate UnaryPredicateMust[T]) (result T, found bool)
}A sequence can be created from a slice using the sequence.FromSlice function:
seq := sequence.FromSlice([]int{1, 2, 3, 4, 5})The ToSlice method returns a slice with the elements of the sequence. This method is useful when you need to pass the elements of the sequence to a function that expects a slice.
seq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
slice := seq.ToSlice()The Each method applies a function to each element of the sequence. The function must have the following signature:
type ApplyFunc[T any] func(T) errorseq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
err := seq.Each(func(i int) error {
fmt.Println(i)
return nil
})The WhereMust method filters the elements of the sequence based on a predicate. The predicate must have the following signature:
type UnaryPredicateMust[T any] func(T) boolseq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
filtered, err := seq.WhereMust(func(i int) bool {
return i%2 == 0
})The Where method filters the elements of the sequence based on a predicate that may return an error. The predicate must have the following signature:
type UnaryPredicate[T any] func(T) (bool, error)seq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
filtered := seq.Where(func(i int) (bool, error) {
return i%2 == 0, nil
})The FirstWhere method returns the first element that satisfies a predicate that may return an error. The predicate must have the following signature:
type UnaryPredicate[T any] func(T) (bool, error)seq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
result, found := seq.FirstWhere(func(i int) (bool, error) {
return i%2 == 0, nil
})The EveryMust method returns true if all elements of the sequence satisfy a predicate. The predicate must have the following signature:
type UnaryPredicate[T any] func(T) boolseq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
result := seq.EveryMust(func(i int) bool {
return i > 0
})A sequence transformer is defined by the following interface:
package sequence
type Transformer[T any, U any] interface {
TransformMust(f TransformFuncMust[T, U]) Type[U]
}The Transform method applies a function to each element of the sequence and returns a new sequence with the transformed elements. The function must have the following signature:
type TransformFunc[T any, U any] func(T) (U, error)seq := sequence.FromSlice([]int{1, 2, 3, 4, 5})
transformed := seq.Transform(func(i int) (string, error) {
return strconv.Itoa(i), nil
})This type extends the basic Sequence concepts but the function signatures but the corresponding function signatures accept a context.Context.
sequence.WithContext(context.TODO()).Build({}int{1, 2, 3, 4, 5}).Where(func (ctx context.Context, i int) (bool, error){return i%2, nil })Is an abstraction of an associative container, and implemented for the golang map[K]V type. The Map[K,V] contract definesWhere, WhereMust,
Each, and Every operations analogous to those defined for the Sequence[T] contract.
The Joiner contract defines the operations that join the given maps by key producing a map of keys to a join product as a Map[K, pair.Type[FirstType, SecondType]
type Joiner[SecondType,K, FirstType] {
Join(other Map[K, SecondType]) Map[K, pair.Pair[FirstType, SecondType]], error
JoinMust(other Map[K, SecondType]) Map[pair.Pair[FirstType, SecondType]]
}func main() {
mapOfInts := map[int]int{1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
mapOfIntToString := map[int]string{1: "one", 2: "two", 3: "three", 4: "four", 5: "five"}
joiner := association.NewJoiner[string](mapOfInts)
joined, err := joiner.Join(mapOfIntToString)
if err != nil {
fmt.Println("error: ", err)
} else {
fmt.Println("joined map")
_ = joined.Each(examples.PrintItem[pair.Type[int, string]])
}
}joined map
1: {1 one}
2: {2 two}
3: {3 three}
4: {4 four}
5: {5 five}
Map transformer operates analogously to the sequence Transform.
func main() {
mapOfIntToString := association.NewMapTransform[string](mapOfInts).TransformMust(func(v int) string {
return fmt.Sprintf("%d", v)
})
}1: 1
2: 2
3: 3
4: 4
5: 5
The Channel contract defines the operations that can be performed on a channel. The Channel[T] contract defines Send, Receive, and Close operations.
func main() {
var err error
ctx := context.TODO()
dlCtx, cancelFunc := context.WithDeadline(ctx, time.Now().Add(1*time.Second))
defer cancelFunc()
ch := stream.NewChan[int]()
sliceOfInts := sequence.FromSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20})
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
err = stream.SendSequence(ch, sliceOfInts)
if err != nil {
fmt.Println(err)
}
}()
outputSequence, _ := stream.IteratorToSlice(dlCtx, ch)
wg.Wait()
err = outputSequence.Each(examples.PrintItem[int])
if err != nil {
fmt.Println(err)
}
}