Collection is a comprehensive Go package that brings functional programming paradigms to Go with type-safe generics. Transform your slice and map operations from verbose loops into elegant, chainable operations that are both performant and readable.
- 🎯 Type-Safe Generics: Full Go 1.18+ generics support with compile-time type safety
- ⚡ High Performance: Optimized implementations with minimal memory allocations
- 🔒 Thread-Safe: Built-in concurrent-safe map operations
- 🔗 Functional Style: Chainable operations inspired by functional programming
- 📦 Zero Dependencies: Pure Go implementation with no external dependencies
- 🧪 Well Tested: Comprehensive test suite ensuring reliability
go get github.com/sergeydobrodey/collectionimport "github.com/sergeydobrodey/collection"Transform your data with ease using functional programming patterns:
// Transform slice elements
users := []User{{ID: 1, Name: "Alice", Age: 32, Active: false}, {ID: 2, Name: "Bob", Age: 8, Active: true}}
names := collection.TransformBy(users, func(u User) string { return u.Name })
// Result: ["Alice", "Bob"]
// Use struct methods as transformers
users := []User{{ID: 1, Name: "Alice", Age: 32, Active: false}, {ID: 2, Name: "Bob", Age: 8, Active: true}}
names := collection.TransformBy(users, User.GetAge)
// Result: [32, 8]
// Filter with predicates
adults := collection.FilterBy(users, func(u User) bool { return u.Age >= 18 })
// Chain operations naturally
activeUserNames := collection.TransformBy(
collection.FilterBy(users, User.IsActive),
func(u User) string { return u.Name },
)// Convert slices to maps instantly
userMap := collection.SliceToMap(users, func(u User) int { return u.ID })
// Result: map[1:User{ID: 1, Name: "Alice", Age: 32, Active: false} 2:User{ID: 2, Name: "Bob", Age: 8, Active: true}]
// Transform map values
uppercaseNames := collection.MapTransformBy(userMap, func(u User) string {
return strings.ToUpper(u.Name)
})
// Find first user over 18
if adult, found := collection.MapFirst(userMap, func(id int, u User) bool {
return u.Age >= 18
}); found {
fmt.Printf("First adult: %s\n", adult.Value.Name)
}
// Get any arbitrary user from the map (without specific condition)
if anyUser, found := collection.MapFirst(userMap, func(id int, u User) bool {
return true // Accept any element
}); found {
fmt.Printf("Got user: %s (ID: %d)\n", anyUser.Value.Name, anyUser.Key)
}
// Check if any users are active (existence check)
_, hasActiveUsers := collection.MapFirst(userMap, func(id int, u User) bool {
return u.Active
})
if hasActiveUsers {
fmt.Printf("Found at least one active user\n")
}// Thread-safe map for concurrent access
syncMap := &collection.SyncMap[string, int]{}
// Safe concurrent operations
syncMap.Store("key", 42)
value, ok := syncMap.Load("key")
syncMap.CompareAndSwap("key", 42, 100)// Merge multiple channels elegantly
worker1Done := make(chan struct{}, 128)
worker2Done := make(chan struct{}, 128)
allDone := collection.ChannelsMerge(worker1Done, worker2Done)
// Async transformations with context
results, err := collection.AsyncTryTransformBy(ctx, urls, fetchData)| Function | Description | Example Use Case |
|---|---|---|
TransformBy |
Transform elements to new type | Convert structs to IDs |
FilterBy |
Filter elements by predicate | Get active users |
Aggregate |
Reduce slice to single value | Sum, concatenate, etc. |
GroupBy |
Group elements by key function | Group users by department |
ChunkBy |
Split slice into smaller chunks | Batch processing |
Distinct |
Remove duplicates | Unique IDs |
Intersection |
Find common elements | Common interests |
Difference |
Find unique elements | Missing items |
Clone |
Create shallow copy of slice | Safe data manipulation |
| Function | Description | Example Use Case |
|---|---|---|
All |
Check if all elements match predicate | All users validated |
Any |
Check if any element matches predicate | Any errors present |
Contains |
Check if slice contains element | User exists |
Equal |
Compare two slices for equality | Data consistency |
EqualFunc |
Compare slices with custom equality function | Custom comparison logic |
| Function | Description | Example Use Case |
|---|---|---|
MapTransformBy |
Transform map values | Normalize data |
MapFilterBy |
Filter map entries | Active sessions only |
MapToSlice |
Convert map to slice | Extract values |
MapKeys / MapValues |
Extract keys or values (order not guaranteed) | Get all IDs |
MapClone |
Create shallow copy of map | Safe data manipulation |
MapEqualFunc |
Compare maps with custom value equality function | Custom value comparison |
MapFirst |
Find first key-value pair matching predicate (order not deterministic) | Get any valid element, check existence, find by condition |
| Function | Description | Example Use Case |
|---|---|---|
AsyncTransformBy |
Parallel transformations | Concurrent API calls |
AsyncTryTransformBy |
Parallel with error handling | Safe concurrent operations |
ChannelsMerge |
Combine multiple channels | Wait for multiple workers |
type Order struct {
ID int
UserID int
Amount float64
Status string
Created time.Time
}
// Complex data processing in a readable pipeline
func ProcessRecentOrders(orders []Order) map[int]float64 {
// Get recent, completed orders grouped by user
recentCompleted := collection.FilterBy(orders, func(o Order) bool {
return o.Status == "completed" &&
time.Since(o.Created) < 24*time.Hour
})
// Group by user and calculate totals
return collection.MapTransformBy(
collection.GroupBy(recentCompleted, func(o Order) int { return o.UserID }),
func(userOrders []Order) float64 {
return collection.Aggregate(userOrders, func(sum float64, o Order) float64 {
return sum + o.Amount
})
},
)
}func FetchUserProfiles(userIDs []int) ([]UserProfile, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Fetch all profiles concurrently with error handling
return collection.AsyncTryTransformBy(ctx, userIDs, func(ctx context.Context, id int) (UserProfile, error) {
return fetchUserProfile(ctx, id)
})
}type UserCache struct {
users *collection.SyncMap[int, User]
}
func (c *UserCache) GetOrFetch(userID int) (User, error) {
// Try to load from cache first
if user, ok := c.users.Load(userID); ok {
return user, nil
}
// Fetch and store atomically
user, err := fetchUser(userID)
if err != nil {
return User{}, err
}
actual, loaded := c.users.LoadOrStore(userID, user)
return actual, nil
}Collection is designed for performance with minimal allocations:
- Memory Efficient: Reuses slices where possible, minimal allocations
- CPU Optimized: Efficient algorithms with O(n) complexity for most operations
- Concurrent Safe: Lock-free operations where possible in SyncMap
We welcome contributions! Here's how you can help:
- 🐛 Report Bugs: Open an issue with reproduction steps
- 💡 Feature Requests: Suggest new utility functions
- 📖 Documentation: Improve examples and documentation
- 🧪 Tests: Add test cases for edge cases
This project is licensed under the MIT License - see the LICENSE file for details.
If this library helps you build better Go applications, please consider:
- ⭐ Starring the repository
- 🐛 Reporting issues
- 📢 Sharing with the Go community
- 💡 Contributing new features
Made with ❤️ for the Go community
Transform your Go code from imperative to functional - one collection at a time.