Golang Samber Lo
Samuel BertheCommunityCreated by samberDistributed by Samuel Berthe
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The samber/lo library brings Lodash-inspired functional programming patterns to Go. It provides a comprehensive suite of type-safe, generic functions for manipulating slices, maps, channels, and strings. By offering immutable-by-default operations, it helps developers reduce boilerplate code associated with manual loops while maintaining type safety and avoiding reflection. The library includes specialized sub-packages for parallel processing (lop), in-place mutation (lom), and lazy evaluation (loi), allowing developers to scale from simple data transformations to performance-optimized pipelines.
What it does
- Provides 500+ generic functions for common data manipulation tasks like Map, Filter, Reduce, and GroupBy.
- Supports immutable operations by default to ensure safer concurrent reads.
- Includes specialized packages for parallel execution (lop) and in-place mutation (lom) for performance tuning.
- Offers lazy iterator support (loi) for Go 1.23+ to minimize memory allocations in transformation chains.
- Includes error-handling variants for common functions to simplify control flow.
- Maintains zero external dependencies, relying solely on the Go standard library.
When to use it
- When you need to perform complex data transformations on slices or maps that would otherwise require verbose manual loops.
- When you want to adopt a more declarative, functional coding style in your Go projects.
- When you need to handle errors during collection processing using built-in error-propagating variants.
- When profiling indicates that standard library approaches are insufficient and you need parallel or lazy evaluation strategies.
- When you need to perform set operations or complex grouping tasks efficiently.
Advantages
- Eliminates boilerplate code and reduces the surface area for logic errors in loops.
- Type-safe generics ensure compile-time checking without the overhead of interface boxing.
- Composable design allows chaining operations cleanly.
- Progressive complexity allows starting with simple helpers and upgrading to performance-oriented variants only when necessary.
- Zero dependencies minimize supply chain risks.
Usage examples
- “Use lo.Map to extract names from a slice of user structs.”
- The agent generates a concise lo.Map call, replacing a manual for-loop and make-slice initialization.
- “How do I group tasks by status using samber/lo?”
- The agent provides a snippet using lo.GroupBy, demonstrating how to transform a slice into a map of slices.
- “I have a large slice and need to filter and map it without extra allocations.”
- The agent suggests using the loi (lazy iterator) package to chain operations lazily, avoiding intermediate slice allocations.
- “My code is failing on the first error during a map operation; how can I fix this?”
- The agent recommends switching to lo.MapErr, which stops processing immediately upon encountering an error and returns the error value.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/samber/golang-samber-lo/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip golang-samber-lo.zip -d .agents/skills
Documentation by samber
Persona: You are a Go engineer who prefers declarative collection transforms over manual loops. You reach for lo to eliminate boilerplate, but you know when the stdlib is enough and when to upgrade to lop, lom, or loi.
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 — refer to library documentation and code examples for more information:
For Go package docs, symbols, versions, importers, and known vulnerabilities, → See
samber/cc-skills-golang@golang-pkg-go-devskill (godig), preferred over Context7 for Go package facts.To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See
samber/cc-skills-golang@golang-goplsskill (gopls).Context7 remains a fallback for docs not indexed on pkg.go.dev.
Why samber/lo
Go's stdlib slices and maps packages cover ~10 basic helpers (sort, contains, keys). Everything else — Map, Filter, Reduce, GroupBy, Chunk, Flatten, Zip — requires manual for-loops. lo fills this gap:
Type-safe generics — no
interface{}casts, no reflection, compile-time checking, no interface boxing overheadImmutable 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
lo, upgrade tolop/lom/loionly when profiling demands itError variants — most functions have
Errsuffixes (MapErr,FilterErr,ReduceErr) that stop on first error
Installation
go get github.com/samber/lo| Package | Import | Alias | Go version |
|---|---|---|---|
| Core (immutable) | github.com/samber/lo | lo | 1.18+ |
| Parallel | github.com/samber/lo/parallel | lop | 1.18+ |
| Mutable | github.com/samber/lo/mutable | lom | 1.18+ |
| Iterator | github.com/samber/lo/it | loi | 1.23+ |
| SIMD (experimental) | github.com/samber/lo/exp/simd | — | 1.25+ (amd64 only) |
Choose the Right Package
Start with lo. Move to other packages only when profiling shows a bottleneck or when lazy evaluation is explicitly needed.
| Package | Use when | Trade-off |
|---|---|---|
lo | Default for all transforms | Allocates new collections (safe, predictable) |
lop | CPU-bound work on large datasets (1000+ items) | Goroutine overhead; not for I/O or small slices |
lom | Hot path confirmed by pprof -alloc_objects | Mutates input — caller must understand side effects |
loi | Large datasets with chained transforms (Go 1.23+) | Lazy evaluation saves memory but adds iterator complexity |
simd | Numeric bulk ops after benchmarking (experimental) | Unstable API, may break between versions |
Key rules:
lopis for CPU parallelism, not I/O concurrency — for I/O fan-out, useerrgroupinsteadlombreaks immutability — only use when allocation pressure is measured, never assumedloieliminates intermediate allocations in chains likeMap → Filter → Takeby evaluating lazilyFor reactive/streaming pipelines over infinite event streams, → see
samber/cc-skills-golang@golang-samber-roskill +samber/ropackage
For detailed package comparison and decision flowchart, see Package Guide.
Core Patterns
Transform a slice
// ✓ 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
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
byStatus := lo.GroupBy(tasks, func(t Task, _ int) string {
return t.Status
})
// map[string][]Task{"open": [...], "closed": [...]}Error variant — stop on first error
results, err := lo.MapErr(urls, func(url string, _ int) (Response, error) {
return http.Get(url)
})Common Mistakes
| Mistake | Why it fails | Fix |
|---|---|---|
Using lo.Contains when slices.Contains exists | Unnecessary dependency for a stdlib-covered op | Prefer slices.Contains/slices.Sort since Go 1.21+ and slices.Collect(maps.Keys(m)) since Go 1.23+ when a key slice is needed |
Using lop.Map on 10 items | Goroutine creation overhead exceeds transform cost | Use lo.Map — lop benefits start at ~1000+ items for CPU-bound work |
Assuming lo.Filter modifies the input | lo is immutable by default — it returns a new slice | Use lom.Filter if you explicitly need in-place mutation |
Using lo.Must in production code paths | Must 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 loi (lazy iterators) to avoid intermediate allocations |
Best Practices
Prefer stdlib when available —
slices.Containsandslices.Sort(Go 1.21+) carry no dependency;maps.Keysis Go 1.23+ and returns an iterator, so useslices.Collect(maps.Keys(m))when you need a slice. Uselofor transforms the stdlib doesn't offer (Map, Filter, Reduce, GroupBy, Chunk, Flatten)Compose lo functions — chain
lo.Filter→lo.Map→lo.GroupByinstead of writing nested loops. Each function is a building blockProfile before optimizing — switch from
lotolom/loponly aftergo tool pprofconfirms allocation or CPU as the bottleneckUse error variants — prefer
lo.MapErroverlo.Map+ manual error collection. Error variants stop early and propagate cleanlyUse
lo.Mustonly in tests and init — in production, handle errors explicitly
Quick Reference
| Function | What it does |
|---|---|
lo.Map | Transform each element |
lo.Filter / lo.Reject | Keep / remove elements matching predicate |
lo.Reduce | Fold elements into a single value |
lo.ForEach | Side-effect iteration |
lo.GroupBy | Group elements by key |
lo.Chunk | Split into fixed-size batches |
lo.Flatten | Flatten nested slices one level |
lo.Uniq / lo.UniqBy | Remove duplicates |
lo.Find / lo.FindOrElse | First match or default |
lo.Contains / lo.Every / lo.Some | Membership tests |
lo.Keys / lo.Values | Extract map keys or values |
lo.PickBy / lo.OmitBy | Filter map entries |
lo.Zip2 / lo.Unzip2 | Pair/unpair two slices |
lo.Range / lo.RangeFrom | Generate number sequences |
lo.Ternary / lo.If | Inline conditionals |
lo.ToPtr / lo.FromPtr | Pointer helpers |
lo.Must / lo.Try | Panic-on-error / recover-as-bool |
lo.Async / lo.Attempt | Async execution / retry with backoff |
lo.Debounce / lo.Throttle | Rate limiting |
lo.ChannelDispatcher | 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-roskill for reactive/streaming pipelines over infinite event streams (samber/ropackage)→ See
samber/cc-skills-golang@golang-samber-moskill for monadic types (Option, Result, Either) that compose with lo transforms→ See
samber/cc-skills-golang@golang-data-structuresskill for choosing the right underlying data structure→ See
samber/cc-skills-golang@golang-performanceskill for profiling methodology before switching tolom/lop
Files
- ATTRIBUTION.mdAdded by AutoGineer905 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md9.6 KiB
- evals/evals.json19.0 KiB
- references/advanced-patterns.md5.0 KiB
- references/api-reference.md18.5 KiB
- references/package-guide.md6.7 KiB
references/api-reference.md
API Reference
Complete function catalog for samber/lo organized by domain.
For up-to-date signatures, use godig symbol doc github.com/samber/lo <Symbol> (→ samber/cc-skills-golang@golang-pkg-go-dev) or check pkg.go.dev/github.com/samber/lo. Context7 is a fallback if a symbol is not indexed there.
Table of Contents
Slice Transformations
Slice-to-map conversions
Error variants
Slice Queries
Slice Set Operations
Slice trimming
Map Operations
String Operations
Math & Comparison
Conditionals
Tuples
Channel Operations
Concurrency Helpers
Type Manipulation
Function Helpers
Duration Helpers
Error Helpers
Slice Transformations
| Function | Description |
|---|---|
lo.Map(s, fn) | Transform each element. fn(item T, index int) R |
lo.MapErr(s, fn) | Map with error — stops on first error |
lo.UniqMap(s, fn) | Map + deduplicate results in one pass |
lo.Filter(s, fn) | Keep elements where predicate returns true |
lo.FilterErr(s, fn) | Filter with error propagation |
lo.Reject(s, fn) | Remove elements where predicate returns true (inverse of Filter) |
lo.RejectMap(s, fn) | Reject + map in one pass |
lo.FilterReject(s, fn) | Split into (matching, non-matching) slices |
lo.FlatMap(s, fn) | Map then flatten one level |
lo.FlatMapErr(s, fn) | FlatMap with error propagation |
lo.FilterMap(s, fn) | Combined filter + map in one pass. fn returns (R, bool) |
lo.Reduce(s, fn, init) | Fold left into accumulator |
lo.ReduceRight(s, fn, init) | Fold right into accumulator |
lo.ForEach(s, fn) | Iterate with side effects |
lo.ForEachWhile(s, fn) | Iterate until fn returns false |
lo.Times(n, fn) | Call fn(index) n times, collect results |
lo.Chunk(s, size) | Split into batches of size |
lo.Window(s, size) | Sliding window of size over slice |
lo.Sliding(s, size) | Sliding window (overlapping), alias for Window |
lo.Flatten(s) | Flatten [][]T → []T (one level) |
lo.Concat(slices...) | Concatenate multiple slices |
lo.Interleave(slices...) | Interleave elements from multiple slices |
lo.Repeat(n, val) | Create slice of n copies of val |
lo.RepeatBy(n, fn) | Create slice of n values from fn(index) |
lo.Splice(s, i, elements...) | Insert elements at index |
lo.Fill(s, val) | Fill slice with value (returns new slice) |
lo.Reverse(s) | Reverse order (returns new slice) |
lo.Shuffle(s) | Random shuffle (returns new slice) |
lo.Clone(s) | Shallow copy of slice |
Slice-to-map conversions
| Function | Description |
|---|---|
lo.KeyBy(s, fn) | Slice to map by key extractor. fn(T) K |
lo.Keyify(s, fn) | Alias for KeyBy |
lo.SliceToMap(s, fn) | Slice to map. fn(T) (K, V) |
lo.Associate(s, fn) | Alias for SliceToMap |
lo.FilterSliceToMap(s, fn) | Filter + slice-to-map. fn(T) (K, V, bool) |
lo.GroupBy(s, fn) | Group into map[K][]V by key function |
lo.GroupByMap(s, fn) | GroupBy returning map[K]R with transform |
Error variants
Most transform functions have Err suffixes: MapErr, FlatMapErr, FilterErr, ReduceErr, ReduceRightErr, ForEachErr, GroupByErr, UniqByErr, etc. These stop processing on the first error and return (result, error).
Slice Queries
| Function | Description |
|---|---|
lo.Find(s, fn) | First element matching predicate. Returns (T, bool) |
lo.FindOrElse(s, fallback, fn) | First match or fallback value |
lo.FindIndexOf(s, fn) | First match with index. Returns (T, int, bool) |
lo.FindLastIndexOf(s, fn) | Last match with index |
lo.FindKey(m, val) | Find key by value in map |
lo.FindKeyBy(m, fn) | Find key by predicate in map |
lo.IndexOf(s, val) | Index of first occurrence (-1 if not found) |
lo.LastIndexOf(s, val) | Index of last occurrence |
lo.Contains(s, val) | True if slice contains value. Note: prefer slices.Contains (stdlib Go 1.21+) |
lo.ContainsBy(s, fn) | True if any element matches predicate |
lo.Every(s, subset) | True if all subset elements are in s |
lo.EveryBy(s, fn) | True if all elements match predicate |
lo.Some(s, subset) | True if any subset element is in s |
lo.SomeBy(s, fn) | True if any element matches predicate |
lo.None(s, subset) | True if no subset element is in s |
lo.NoneBy(s, fn) | True if no element matches predicate |
lo.Count(s, val) | Count occurrences of value |
lo.CountBy(s, fn) | Count elements matching predicate |
lo.CountValues(s) | Frequency map map[T]int |
lo.CountValuesBy(s, fn) | Frequency map by key function |
lo.Min(s) / lo.Max(s) | Min/max of comparable slice |
lo.MinBy(s, fn) / lo.MaxBy(s, fn) | Min/max by comparison function |
lo.MinIndex(s) / lo.MaxIndex(s) | Index of min/max element |
lo.MinIndexBy(s, fn) / lo.MaxIndexBy(s, fn) | Index of min/max by comparison |
lo.Earliest(vals...) | Earliest time.Time value |
lo.EarliestBy(s, fn) | Earliest by extractor function |
lo.Latest(vals...) | Latest time.Time value |
lo.LatestBy(s, fn) | Latest by extractor function |
lo.First(s) / lo.Last(s) | First/last element. Returns (T, bool) |
lo.FirstOr(s, fallback) | First element or fallback |
lo.FirstOrEmpty(s) | First element or zero-value |
lo.LastOr(s, fallback) | Last element or fallback |
lo.LastOrEmpty(s) | Last element or zero-value |
lo.Nth(s, n) | Element at index n (supports negative). Returns (T, error) |
lo.NthOr(s, n, fallback) | Nth element or fallback |
lo.NthOrEmpty(s, n) | Nth element or zero-value |
lo.Sample(s) | Random element |
lo.SampleBy(s, fn) | Random element matching predicate |
lo.Samples(s, n) | n random elements |
lo.SamplesBy(s, n, fn) | n random elements matching predicate |
lo.IsSorted(s) / lo.IsSortedBy(s, fn) | Check if slice is sorted |
lo.HasPrefix(s, prefix) | True if slice starts with prefix elements |
lo.HasSuffix(s, suffix) | True if slice ends with suffix elements |
Slice Set Operations
| Function | Description |
|---|---|
lo.Uniq(s) | Remove duplicates (preserves first occurrence) |
lo.UniqBy(s, fn) | Remove duplicates by key function |
lo.PartitionBy(s, fn) | Split into groups of consecutive elements with same key |
lo.Compact(s) | Remove zero-value elements |
lo.Without(s, vals...) | Remove specific values |
lo.WithoutBy(s, fn) | Remove elements matching predicate |
lo.WithoutEmpty(s) | Remove zero-value elements (alias for Compact) |
lo.WithoutNth(s, indices...) | Remove elements at specific indices |
lo.Union(slices...) | Combine slices, remove duplicates |
lo.Intersect(a, b) | Elements present in both slices |
lo.IntersectBy(a, b, fn) | Intersection by key function |
lo.Difference(a, b) | Elements in a but not in b |
lo.Replace(s, old, new, n) | Replace first n occurrences |
lo.ReplaceAll(s, old, new) | Replace all occurrences |
lo.FindDuplicates(s) | Elements that appear more than once |
lo.FindDuplicatesBy(s, fn) | Duplicates by key function |
lo.FindUniques(s) | Elements that appear exactly once |
lo.FindUniquesBy(s, fn) | Unique elements by key function |
lo.ElementsMatch(a, b) | True if same elements regardless of order |
lo.ElementsMatchBy(a, b, fn) | ElementsMatch by comparison function |
lo.Subset(s, offset, length) | Sub-slice from offset with length |
lo.Slice(s, start, end) | Sub-slice with bounds (safe, no panic) |
Slice trimming
| Function | Description |
|---|---|
lo.Take(s, n) | First n elements |
lo.TakeWhile(s, fn) | Take while predicate is true |
lo.TakeFilter(s, n, fn) | Take first n elements matching predicate |
lo.Drop(s, n) | Skip first n elements |
lo.DropRight(s, n) | Skip last n elements |
lo.DropWhile(s, fn) | Drop while predicate is true |
lo.DropRightWhile(s, fn) | Drop from right while true |
lo.DropByIndex(s, indices...) | Drop elements at specific indices |
lo.Cut(s, start, end) | Remove elements between start and end |
lo.CutPrefix(s, prefix) | Remove prefix from slice |
lo.CutSuffix(s, suffix) | Remove suffix from slice |
lo.Trim(s, fn) | Trim both ends while predicate is true |
lo.TrimLeft(s, fn) | Trim left while predicate is true |
lo.TrimRight(s, fn) | Trim right while predicate is true |
lo.TrimPrefix(s, prefix) | Remove exact prefix elements |
lo.TrimSuffix(s, suffix) | Remove exact suffix elements |
Map Operations
| Function | Description |
|---|---|
lo.Keys(m) | All keys as a slice. Note: for Go 1.23+, prefer slices.Collect(maps.Keys(m)) when stdlib coverage is enough |
lo.UniqKeys(m) | Unique keys (useful for multi-maps) |
lo.Values(m) | All values |
lo.UniqValues(m) | Unique values |
lo.HasKey(m, key) | True if key exists |
lo.ValueOr(m, key, fallback) | Value or fallback if key missing |
lo.PickBy(m, fn) | Keep entries where predicate is true |
lo.PickByKeys(m, keys) | Keep only specified keys |
lo.PickByValues(m, vals) | Keep only specified values |
lo.OmitBy(m, fn) | Remove entries where predicate is true |
lo.OmitByKeys(m, keys) | Remove specified keys |
lo.OmitByValues(m, vals) | Remove specified values |
lo.FilterKeys(m, fn) | Keep entries where key matches predicate |
lo.FilterValues(m, fn) | Keep entries where value matches predicate |
lo.MapKeys(m, fn) | Transform keys |
lo.MapValues(m, fn) | Transform values |
lo.MapEntries(m, fn) | Transform both key and value |
lo.MapToSlice(m, fn) | Convert map entries to slice |
lo.FilterMapToSlice(m, fn) | Filter + map-to-slice in one pass |
lo.Entries(m) / lo.ToPairs(m) | Map → []lo.Entry[K,V] |
lo.FromEntries(entries) / lo.FromPairs(pairs) | []lo.Entry → map |
lo.Invert(m) | Swap keys and values |
lo.Assign(maps...) | Merge maps (last wins) |
lo.ChunkEntries(m, size) | Split map into chunks of size entries |
String Operations
| Function | Description |
|---|---|
lo.Substring(s, offset, length) | Safe substring (rune-aware) |
lo.ChunkString(s, size) | Split string into chunks |
lo.RuneLength(s) | Count runes (not bytes) |
lo.PascalCase(s) | "hello world" → "HelloWorld" |
lo.CamelCase(s) | "hello world" → "helloWorld" |
lo.KebabCase(s) | "hello world" → "hello-world" |
lo.SnakeCase(s) | "hello world" → "hello_world" |
lo.Words(s) | Split into words |
lo.Capitalize(s) | Capitalize first letter |
lo.Ellipsis(s, maxLen) | Truncate with … |
lo.RandomString(n, charset) | Generate random string |
Math & Comparison
| Function | Description |
|---|---|
lo.Range(n) | [0, 1, ..., n-1] |
lo.RangeFrom(start, n) | [start, start+1, ..., start+n-1] |
lo.RangeWithSteps(start, end, step) | Custom step range |
lo.Clamp(val, min, max) | Constrain value to range |
lo.Sum(s) | Sum of numeric slice |
lo.SumBy(s, fn) | Sum by extractor function |
lo.Product(s) / lo.ProductBy(s, fn) | Product of elements |
lo.Mean(s) / lo.MeanBy(s, fn) | Arithmetic mean |
lo.Mode(s) | Most frequent element(s) |
Conditionals
| Function | Description |
|---|---|
lo.Ternary(cond, a, b) | Inline if/else (both values evaluated) |
lo.TernaryF(cond, fnA, fnB) | Lazy ternary (only winning branch evaluated) |
lo.If(cond, val).ElseIf(cond2, val2).Else(val3) | Chained conditional |
lo.IfF(cond, fn).ElseIfF(cond2, fn2).ElseF(fn3) | Chained conditional with lazy evaluation |
lo.Switch[R](val).Case(v1, r1).Case(v2, r2).Default(r3) | Pattern matching |
Tuples
| Function | Description |
|---|---|
lo.T2(a, b) ... lo.T9(...) | Create tuple from values |
lo.Unpack2(t) ... lo.Unpack9(t) | Destructure tuple into values |
lo.Zip2(a, b) ... lo.Zip9(...) | Pair elements from multiple slices |
lo.ZipBy2(a, b, fn) ... lo.ZipBy9(...) | Zip with custom merge function |
lo.Unzip2(pairs) ... lo.Unzip9(...) | Split pairs back into slices |
lo.UnzipBy2(s, fn) ... lo.UnzipBy9(...) | Unzip with custom split function |
lo.CrossJoin2(a, b) ... lo.CrossJoin9(...) | Cartesian product of slices |
lo.CrossJoinBy2(a, b, fn) ... lo.CrossJoinBy9(...) | Cartesian product with transform |
Channel Operations
| Function | Description |
|---|---|
lo.ChannelDispatcher(ch, count, strategy) | Fan-out to multiple channels. Strategies: RoundRobin, Random, WeightedRandom, First, Least, Most |
lo.SliceToChannel(bufSize, s) | Convert slice to buffered channel |
lo.ChannelToSlice(ch) | Collect channel into slice |
lo.Generator(bufSize, fn) | Create channel from generator function |
lo.Buffer(ch, size) | Buffer channel output |
lo.BufferWithContext(ctx, ch, size) | Buffer with context cancellation |
lo.BufferWithTimeout(ch, size, timeout) | Buffer with timeout |
lo.FanIn(channels...) | Merge multiple channels into one |
lo.FanOut(ch, count) | Duplicate channel to multiple consumers |
Concurrency Helpers
| Function | Description |
|---|---|
lo.Async(fn) | Run function in goroutine, return channel for result |
lo.Async0 ... lo.Async6 | Async with tuple returns |
lo.Attempt(maxRetries, fn) | Retry until success or max retries |
lo.AttemptWithDelay(max, delay, fn) | Retry with fixed delay between attempts |
lo.AttemptWhile(fn) | Retry while predicate returns true |
lo.AttemptWhileWithDelay(delay, fn) | AttemptWhile with delay between attempts |
lo.Debounce(duration, fn) | Debounce — execute after quiet period. Returns (func(), func()) (trigger, cancel) |
lo.DebounceBy(duration, fn) | Debounce by key — separate debounce per key |
lo.Throttle(duration, fn) | Throttle — max one execution per duration |
lo.ThrottleWithCount(duration, count, fn) | Throttle allowing N executions per duration |
lo.ThrottleBy(duration, fn) | Throttle by key — separate throttle per key |
lo.ThrottleByWithCount(duration, count, fn) | ThrottleBy with count |
lo.WaitFor(fn, timeout, heartbeat) | Poll until condition met or timeout |
lo.WaitForWithContext(ctx, fn, ...) | WaitFor with context cancellation |
lo.Synchronize(mutexes...) | Create synchronized wrapper. sync.Locker-based |
lo.Transaction(fn) | Execute function with rollback on error |
Type Manipulation
| Function | Description |
|---|---|
lo.ToPtr(v) | Value to pointer (&v) |
lo.Nil[T]() | Typed nil pointer |
lo.EmptyableToPtr(v) | Value to pointer, zero-value becomes nil |
lo.FromPtr(p) | Pointer to value (zero-value if nil) |
lo.FromPtrOr(p, fallback) | Pointer to value with fallback |
lo.ToSlicePtr(s) | []T → []*T |
lo.FromSlicePtr(s) | []*T → []T (nil becomes zero-value) |
lo.FromSlicePtrOr(s, fallback) | []*T → []T with fallback for nil |
lo.ToAnySlice(s) | []T → []any |
lo.FromAnySlice[T](s) | []any → ([]T, bool) |
lo.IsNil(v) | Nil-safe check (handles interface nil) |
lo.IsNotNil(v) | Inverse of IsNil |
lo.Empty[T]() | Zero-value of type T |
lo.IsEmpty(v) | True if zero-value |
lo.IsNotEmpty(v) | True if not zero-value |
lo.Coalesce(vals...) | First non-zero value |
lo.CoalesceOrEmpty(vals...) | First non-zero or zero-value |
lo.CoalesceSlice(slices...) | First non-empty slice |
lo.CoalesceSliceOrEmpty(slices...) | First non-empty slice or empty |
lo.CoalesceMap(maps...) | First non-empty map |
lo.CoalesceMapOrEmpty(maps...) | First non-empty map or empty |
Function Helpers
| Function | Description |
|---|---|
lo.Partial(fn, arg) | Partial application — bind first argument |
lo.Partial2(fn, arg) ... lo.Partial5(fn, arg) | Partial with 2-5 args |
Duration Helpers
| Function | Description |
|---|---|
lo.Duration(fn) | Measure execution time. Returns time.Duration |
lo.Duration0(fn) ... lo.Duration10(fn) | Duration with 0-10 return values — returns (time.Duration, ...) |
Error Helpers
| Function | Description |
|---|---|
lo.Must(val, err) | Panic if err != nil, return val. Use in tests/init only |
lo.Must0(err) ... lo.Must6(...) | Must with 0-6 return values |
lo.Try(fn) | Run fn, return true if no panic |
lo.Try1(fn) ... lo.Try6(fn) | Try with 1-6 return values |
lo.TryOr(fn, fallback) | Run fn, return fallback on panic |
lo.TryOr1(fn, fallback) ... lo.TryOr6(...) | TryOr with 1-6 return values |
lo.TryCatch(fn, catchFn) | Try with catch handler |
lo.TryWithErrorValue(fn) | Try returning recovered error value |
lo.TryCatchWithErrorValue(fn, catchFn) | TryCatch with error value |
lo.Validate(conditions...) | Return first error from condition list |
lo.ErrorsAs[T](err) | Generic wrapper for errors.As |
lo.Assert[T](v) | Type assertion with panic message |
lo.Assertf[T](v, format, args...) | Type assertion with formatted panic message |
Requirements and compatibility
Written for: Claude Code, OpenAI Codex
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Declares allowed tools, Claude Code frontmatter
The author says: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- samber
- Publisher
- Samuel Berthe (Community)
- Distributed by
- Samuel Berthe
- Source
- samber/cc-skills-golang · skills/golang-samber-lo · commit bb1d43d
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by samber or Samuel Berthe.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download golang-samber-lo.zip