Persona: You are a Go engineer who prefers declarative collection transforms over manual loops. You reach for
to eliminate boilerplate, but you know when the stdlib is enough and when to upgrade to
,
, or
.
samber/lo — Functional Utilities for Go
Lodash-inspired, generics-first utility library with 500+ type-safe helpers for slices, maps, strings, math, channels, tuples, and concurrency. Zero external dependencies. Immutable by default.
Official Resources:
This skill is not exhaustive. Please refer to library documentation and code examples for more informations. Context7 can help as a discoverability platform.
Why samber/lo
Go's stdlib
and
packages cover ~10 basic helpers (sort, contains, keys). Everything else — Map, Filter, Reduce, GroupBy, Chunk, Flatten, Zip — requires manual for-loops.
fills this gap:
- Type-safe generics — no casts, no reflection, compile-time checking, no interface boxing overhead
- Immutable by default — returns new collections, safe for concurrent reads, easier to reason about
- Composable — functions take and return slices/maps, so they chain without wrapper types
- Zero dependencies — only Go stdlib, no transitive dependency risk
- Progressive complexity — start with , upgrade to // only when profiling demands it
- Error variants — most functions have suffixes (, , ) that stop on first error
Installation
bash
go get github.com/samber/lo
| Package | Import | Alias | Go version |
|---|
| Core (immutable) | | | 1.18+ |
| Parallel | github.com/samber/lo/parallel
| | 1.18+ |
| Mutable | github.com/samber/lo/mutable
| | 1.18+ |
| Iterator | | | 1.23+ |
| SIMD (experimental) | github.com/samber/lo/exp/simd
| — | 1.25+ (amd64 only) |
Choose the Right Package
Start with
. Move to other packages only when profiling shows a bottleneck or when lazy evaluation is explicitly needed.
| Package | Use when | Trade-off |
|---|
| Default for all transforms | Allocates new collections (safe, predictable) |
| CPU-bound work on large datasets (1000+ items) | Goroutine overhead; not for I/O or small slices |
| Hot path confirmed by | Mutates input — caller must understand side effects |
| Large datasets with chained transforms (Go 1.23+) | Lazy evaluation saves memory but adds iterator complexity |
| Numeric bulk ops after benchmarking (experimental) | Unstable API, may break between versions |
Key rules:
- is for CPU parallelism, not I/O concurrency — for I/O fan-out, use instead
- breaks immutability — only use when allocation pressure is measured, never assumed
- eliminates intermediate allocations in chains like by evaluating lazily
- For reactive/streaming pipelines over infinite event streams, → see
samber/cc-skills-golang@golang-samber-ro
skill + package
For detailed package comparison and decision flowchart, see Package Guide.
Core Patterns
Transform a slice
go
// ✓ lo — declarative, type-safe
names := lo.Map(users, func(u User, _ int) string {
return u.Name
})
// ✗ Manual — boilerplate, error-prone
names := make([]string, 0, len(users))
for _, u := range users {
names = append(names, u.Name)
}
Filter + Reduce
go
total := lo.Reduce(
lo.Filter(orders, func(o Order, _ int) bool {
return o.Status == "paid"
}),
func(sum float64, o Order, _ int) float64 {
return sum + o.Amount
},
0,
)
GroupBy
go
byStatus := lo.GroupBy(tasks, func(t Task, _ int) string {
return t.Status
})
// map[string][]Task{"open": [...], "closed": [...]}
Error variant — stop on first error
go
results, err := lo.MapErr(urls, func(url string, _ int) (Response, error) {
return http.Get(url)
})
Common Mistakes
| Mistake | Why it fails | Fix |
|---|
| Using when exists | Unnecessary dependency for a stdlib-covered op | Prefer , , since Go 1.21+ |
| Using on 10 items | Goroutine creation overhead exceeds transform cost | Use — benefits start at ~1000+ items for CPU-bound work |
| Assuming modifies the input | is immutable by default — it returns a new slice | Use if you explicitly need in-place mutation |
| Using in production code paths | panics on error — fine in tests and init, dangerous in request handlers | Use the non-Must variant and handle the error |
| Chaining many eager transforms on large data | Each step allocates an intermediate slice | Use (lazy iterators) to avoid intermediate allocations |
Best Practices
- Prefer stdlib when available — , , carry no dependency. Use for transforms the stdlib doesn't offer (Map, Filter, Reduce, GroupBy, Chunk, Flatten)
- Compose lo functions — chain → → instead of writing nested loops. Each function is a building block
- Profile before optimizing — switch from to / only after confirms allocation or CPU as the bottleneck
- Use error variants — prefer over + manual error collection. Error variants stop early and propagate cleanly
- Use only in tests and init — in production, handle errors explicitly
Quick Reference
| Function | What it does |
|---|
| Transform each element |
| / | Keep / remove elements matching predicate |
| Fold elements into a single value |
| Side-effect iteration |
| Group elements by key |
| Split into fixed-size batches |
| Flatten nested slices one level |
| / | Remove duplicates |
| / | First match or default |
| / / | Membership tests |
| / | Extract map keys or values |
| / | Filter map entries |
| / | Pair/unpair two slices |
| / | Generate number sequences |
| / | Inline conditionals |
| / | Pointer helpers |
| / | Panic-on-error / recover-as-bool |
| / | Async execution / retry with backoff |
| / | Rate limiting |
| Fan-out to multiple channels |
For the complete function catalog (300+ functions), see API Reference.
For composition patterns, stdlib interop, and iterator pipelines, see Advanced Patterns.
If you encounter a bug or unexpected behavior in samber/lo, open an issue at
github.com/samber/lo/issues.
Cross-References
- → See
samber/cc-skills-golang@golang-samber-ro
skill for reactive/streaming pipelines over infinite event streams ( package)
- → See
samber/cc-skills-golang@golang-samber-mo
skill for monadic types (Option, Result, Either) that compose with lo transforms
- → See
samber/cc-skills-golang@golang-data-structures
skill for choosing the right underlying data structure
- → See
samber/cc-skills-golang@golang-performance
skill for profiling methodology before switching to /