collection

package module
v1.11.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2025 License: BSD-2-Clause Imports: 7 Imported by: 6

README

Collection

A comprehensive Go library providing generic, type-safe collection utilities and data structures. Leverages Go generics for efficient slice operations, set management, channel processing, and pointer utilities.

Features

  • 🔧 Slice Operations: Filter, Map, Find, Contains, Unique, Reverse, Copy, Exclude, Join
  • 📦 Set Data Structure: Thread-safe generic set with mutex protection
  • ⚡ Channel Processing: Concurrent channel operations with context support
  • 🎯 Pointer Utilities: Generic Ptr/Unptr functions for easy pointer creation
  • ⚖️ Comparison Utilities: Generic equality and string comparison helpers

Installation

go get github.com/bborbe/collection

Quick Start

import "github.com/bborbe/collection"

// Filter slice elements
numbers := []int{1, 2, 3, 4, 5}
evens := collection.Filter(numbers, func(n int) bool { return n%2 == 0 })
// Result: [2, 4]

// Create and use a Set
set := collection.NewSet[string]()
set.Add("hello")
set.Add("world")
fmt.Println(set.Contains("hello")) // true

// Create pointers easily
name := "John"
namePtr := collection.Ptr(name) // *string pointing to "John"

API Reference

Slice Operations
Filter
func Filter[T any](list []T, match func(value T) bool) []T

Returns a new slice containing only elements that match the predicate.

users := []User{{Name: "Alice", Age: 25}, {Name: "Bob", Age: 17}}
adults := collection.Filter(users, func(u User) bool { return u.Age >= 18 })
Find
func Find[T any](list []T, match func(value T) bool) (*T, error)

Returns the first element matching the predicate, or NotFoundError.

user, err := collection.Find(users, func(u User) bool { return u.Name == "Alice" })
if err != nil {
    // Handle not found
}
Map
func Map[T any](list []T, fn func(value T) error) error

Applies a function to each element in the slice, returning the first error encountered.

err := collection.Map(users, func(u User) error {
    return validateUser(u)
})
Unique
func Unique[T comparable](list []T) []T

Returns a new slice with duplicate elements removed, preserving order.

numbers := []int{1, 2, 2, 3, 3, 3}
unique := collection.Unique(numbers) // [1, 2, 3]
Contains
func Contains[T comparable](list []T, search T) bool
func ContainsAll[T comparable](list []T, search []T) bool

Check if slice contains specific element(s).

fruits := []string{"apple", "banana", "cherry"}
hasApple := collection.Contains(fruits, "apple") // true
hasAll := collection.ContainsAll(fruits, []string{"apple", "banana"}) // true
Reverse
func Reverse[T any](list []T) []T

Returns a new slice with elements in reverse order.

numbers := []int{1, 2, 3}
reversed := collection.Reverse(numbers) // [3, 2, 1]
Copy
func Copy[T any](list []T) []T

Creates a shallow copy of the slice.

Exclude
func Exclude[T comparable](list []T, exclude []T) []T

Returns a new slice excluding specified elements.

numbers := []int{1, 2, 3, 4, 5}
filtered := collection.Exclude(numbers, []int{2, 4}) // [1, 3, 5]
Join
func Join[T ~string](list []T, separator string) string

Joins string-like elements with a separator.

words := []string{"hello", "world", "!"}
sentence := collection.Join(words, " ") // "hello world !"
Set Data Structure
Creating Sets
func NewSet[T comparable]() Set[T]

Creates a new thread-safe generic set.

stringSet := collection.NewSet[string]()
intSet := collection.NewSet[int]()
Set Operations
type Set[T comparable] interface {
    Add(element T)
    Remove(element T) 
    Contains(element T) bool
    Slice() []T
    Length() int
}

Example usage:

set := collection.NewSet[string]()
set.Add("apple")
set.Add("banana")
set.Add("apple") // Duplicate, ignored

fmt.Println(set.Length()) // 2
fmt.Println(set.Contains("apple")) // true
fmt.Println(set.Slice()) // ["apple", "banana"] (order not guaranteed)

set.Remove("apple")
fmt.Println(set.Length()) // 1
Pointer Utilities
Ptr
func Ptr[T any](value T) *T

Creates a pointer to the given value.

name := "John"
namePtr := collection.Ptr(name) // *string

age := 25
agePtr := collection.Ptr(age) // *int
Unptr
func Unptr[T any](ptr *T) T
func UnptrWithDefault[T any](ptr *T, defaultValue T) T

Dereferences pointers safely.

var namePtr *string = collection.Ptr("John")
name := collection.Unptr(namePtr) // "John"

var nilPtr *string
name := collection.UnptrWithDefault(nilPtr, "Anonymous") // "Anonymous"
Channel Processing
ChannelFnMap
func ChannelFnMap[T interface{}](
    ctx context.Context,
    getFn func(ctx context.Context, ch chan<- T) error,
    mapFn func(ctx context.Context, t T) error,
) error

Processes data from a producer function through a mapper function concurrently.

err := collection.ChannelFnMap(
    ctx,
    func(ctx context.Context, ch chan<- int) error {
        for i := 0; i < 100; i++ {
            select {
            case ch <- i:
            case <-ctx.Done():
                return ctx.Err()
            }
        }
        return nil
    },
    func(ctx context.Context, num int) error {
        fmt.Printf("Processing: %d\n", num)
        return nil
    },
)
ChannelFnList & ChannelFnCount
func ChannelFnList[T any](ctx context.Context, getFn func(ctx context.Context, ch chan<- T) error) ([]T, error)
func ChannelFnCount[T any](ctx context.Context, getFn func(ctx context.Context, ch chan<- T) error) (int, error)

Collect channel data into a slice or count items.

Comparison Utilities
Equal & Compare
func Equal[T comparable](a, b T) bool
func Compare[T ~string](a, b T) int

Generic comparison functions for any comparable types.

Advanced Examples

Processing Large Datasets Concurrently
ctx := context.Background()

// Process items concurrently with automatic batching
err := collection.ChannelFnMap(
    ctx,
    func(ctx context.Context, ch chan<- WorkItem) error {
        return loadWorkItems(ctx, ch) // Your data loading logic
    },
    func(ctx context.Context, item WorkItem) error {
        return processWorkItem(ctx, item) // Your processing logic
    },
)
Building Complex Data Pipelines
// Load raw data
rawData := loadRawData()

// Filter valid entries
validData := collection.Filter(rawData, func(item DataItem) bool {
    return item.IsValid()
})

// Remove duplicates
uniqueData := collection.Unique(validData)

// Find specific items
importantItem, err := collection.Find(uniqueData, func(item DataItem) bool {
    return item.Priority == "high"
})

// Create a set for fast lookups
processedIDs := collection.NewSet[string]()
for _, item := range uniqueData {
    processedIDs.Add(item.ID)
}

Requirements

  • Go 1.24.5 or later
  • Support for Go generics

Dependencies

  • github.com/bborbe/errors - Enhanced error handling
  • github.com/bborbe/run - Concurrent execution utilities

Testing

go test ./...

License

BSD-style license. See LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NotFoundError = stderrors.New("not found")

NotFoundError is returned when an element is not found in a collection.

Functions

func ChannelFnCount added in v1.1.0

func ChannelFnCount[T interface{}](
	ctx context.Context,
	fn func(ctx context.Context, ch chan<- T) error,
) (int, error)

ChannelFnCount executes a function that sends values to a channel and returns the total count of values sent. Returns -1 if an error occurs.

func ChannelFnList

func ChannelFnList[T interface{}](
	ctx context.Context,
	fn func(ctx context.Context, ch chan<- T) error,
) ([]T, error)

ChannelFnList executes a function that sends values to a channel and collects all the values into a slice. Returns an empty slice if an error occurs.

func ChannelFnMap

func ChannelFnMap[T interface{}](
	ctx context.Context,
	getFn func(ctx context.Context, ch chan<- T) error,
	mapFn func(ctx context.Context, t T) error,
) error

ChannelFnMap executes a function that sends values to a channel and applies a mapping function to each value received from the channel. It runs the getter and mapper functions concurrently and returns the first error encountered.

func Compare added in v1.6.0

func Compare[T ~string](a, b T) int

Compare compares two string-like values and returns an integer comparing a and b. The result will be 0 if a == b, -1 if a < b, and +1 if a > b.

func Contains

func Contains[T comparable](list []T, value T) bool

Contains reports whether the given value is present in the slice.

func ContainsAll added in v1.2.0

func ContainsAll[T comparable](a []T, b []T) bool

ContainsAll returns true if all elements from slice b are present in slice a. It checks whether a is a superset of b (a ⊇ b). Empty slice b always returns true. Duplicate elements in b are treated as single elements.

func Copy added in v1.3.1

func Copy[T any](values []T) []T

Copy returns a new slice that is a shallow copy of the input slice.

func Equal added in v1.2.0

func Equal[T comparable](a []T, b []T) bool

Equal reports whether two slices are equal by comparing their lengths and elements in order.

func Exclude

func Exclude[T comparable](list []T, excludes ...T) []T

Exclude returns a new slice with all elements from the input slice except those specified in the excludes parameter.

func Filter

func Filter[T any](list []T, match func(value T) bool) []T

Filter returns a new slice containing only the elements from the input slice that satisfy the given predicate function.

func Find

func Find[T any](list []T, match func(value T) bool) (*T, error)

Find returns a pointer to the first element in the slice that satisfies the predicate function. If no element is found, it returns nil and NotFoundError.

func Join added in v1.7.0

func Join[T any](a []T, b []T) []T

Join allow to join two arrays into one new array

func Map added in v1.5.0

func Map[T any](list []T, fn func(value T) error) error

Map applies the given function to each element in the slice. If any function call returns an error, Map stops and returns that error.

func Ptr

func Ptr[T any](value T) *T

Ptr returns a pointer to the given value.

func Reverse

func Reverse[T any](values []T) []T

Reverse returns a new slice with the elements in reverse order.

func StreamList added in v1.8.0

func StreamList[T any](ctx context.Context, list []T, ch chan<- T) error

StreamList streams the given list into the given channel. It returns early if the context is canceled.

func UnPtr

func UnPtr[T any](ptr *T) T

UnPtr dereferences a pointer and returns the value. If the pointer is nil, it returns the zero value of type T.

func Unique

func Unique[T comparable](list []T) []T

Unique returns a new slice containing only the unique elements from the input slice. The order of the first occurrence of each element is preserved.

Types

type HasEqual added in v1.3.1

type HasEqual[V any] interface {
	Equal(value V) bool
}

HasEqual represents types that can compare themselves for equality with another value.

type HasHashCode added in v1.3.1

type HasHashCode interface {
	HashCode() string
}

HasHashCode represents types that can provide a string hash code for themselves.

type Set added in v1.3.0

type Set[T comparable] interface {
	// Add inserts elements into the set. Duplicate elements are automatically ignored.
	// Multiple elements can be added in a single call with only one mutex lock.
	Add(elements ...T)
	// Remove deletes an element from the set.
	Remove(element T)
	// Contains reports whether an element is present in the set.
	Contains(element T) bool
	// Slice returns all elements as a slice in arbitrary order.
	Slice() []T
	// Length returns the number of elements in the set.
	Length() int
}

Set represents a thread-safe collection of unique elements. This implementation uses a map for O(1) average-case lookups, additions, and deletions.

func NewSet added in v1.3.0

func NewSet[T comparable](elements ...T) Set[T]

NewSet creates a new thread-safe set for comparable types. It accepts optional initial elements to populate the set. Duplicate elements are automatically handled.

Performance: This implementation uses a map-based approach with O(1) average-case operations for Add, Remove, and Contains. Initialization is O(n) for n elements.

Example:

set := collection.NewSet(1, 2, 3)
empty := collection.NewSet[int]()

type SetEqual added in v1.3.1

type SetEqual[T HasEqual[T]] interface {
	// Add inserts elements into the set, using the Equal method for uniqueness checking.
	// Duplicate elements are automatically ignored.
	// Multiple elements can be added in a single call with only one mutex lock.
	Add(elements ...T)
	// Remove deletes an element from the set using its Equal method for matching.
	Remove(element T)
	// Contains reports whether an element matching the given value is present in the set.
	Contains(element T) bool
	// Slice returns all elements as a slice in arbitrary order.
	Slice() []T
	// Length returns the number of elements in the set.
	Length() int
}

SetEqual represents a thread-safe set for types that implement HasEqual. Elements are uniquely identified by their Equal method.

Performance: This implementation uses a slice-based approach. Operations have O(n) complexity where n is the number of elements. For large sets or performance-critical code, consider using SetHashCode which provides O(1) average-case operations.

func NewSetEqual added in v1.3.1

func NewSetEqual[T HasEqual[T]](elements ...T) SetEqual[T]

NewSetEqual creates a new thread-safe set for types that implement HasEqual. It accepts optional initial elements to populate the set. Duplicate elements are automatically handled using the Equal method.

Performance: This implementation uses a slice-based approach with O(n) operations. Initialization with k elements has O(k²) complexity due to uniqueness checks. For better performance with large sets, use NewSetHashCode instead.

Example:

type User struct { ID int; Name string }
func (u User) Equal(other User) bool { return u.ID == other.ID }
set := collection.NewSetEqual(User{1, "Alice"}, User{2, "Bob"})

type SetHashCode added in v1.3.1

type SetHashCode[T HasHashCode] interface {
	// Add inserts elements into the set, using their hash codes for uniqueness.
	// Duplicate elements (same hash code) are automatically ignored.
	// Multiple elements can be added in a single call with only one mutex lock.
	Add(elements ...T)
	// Remove deletes an element from the set by its hash code.
	Remove(element T)
	// Contains reports whether an element with the given hash code is present in the set.
	Contains(element T) bool
	// Slice returns all elements as a slice in arbitrary order.
	Slice() []T
	// Length returns the number of elements in the set.
	Length() int
}

SetHashCode represents a thread-safe set for types that implement HasHashCode. Elements are uniquely identified by their hash code.

Performance: This implementation uses a map-based approach with O(1) average-case operations for Add, Remove, and Contains. This provides better performance than SetEqual for large sets or performance-critical code.

func NewSetHashCode added in v1.3.1

func NewSetHashCode[T HasHashCode](elements ...T) SetHashCode[T]

NewSetHashCode creates a new thread-safe set for types that implement HasHashCode. It accepts optional initial elements to populate the set. Duplicate elements (same hash code) are automatically handled.

Performance: This implementation uses a map-based approach with O(1) average-case operations. Initialization is O(n) for n elements, making it suitable for large sets.

Example:

type User struct { ID int; Name string }
func (u User) HashCode() string { return fmt.Sprintf("user-%d", u.ID) }
set := collection.NewSetHashCode(User{1, "Alice"}, User{2, "Bob"})

Jump to

Keyboard shortcuts

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