Generated banner for Golang Samber Lo
Generated logo for Golang Samber Lo

Golang Samber Lo

Samuel BertheCommunityCreated by samberDistributed by Samuel Berthe

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

Functional programming helpers for Golang using samber/lo — 500+ type-safe generic functions for slices, maps, channels, strings, math, tuples, and concurrency (Map, Filter, Reduce, GroupBy, Chunk, Flatten, Find, Uniq, etc.). Core immutable package (lo), concurrent variants (lo/parallel aka lop), in-place mutations (lo/mutable aka lom), lazy iterators (lo/it aka loi for Go 1.23+), and experimental SIMD (lo/exp/simd). Apply when using or adopting samber/lo, when the codebase imports github.com/samber/lo, or when implementing functional-style data transformations in Go. Not for streaming pipelines (→ See `samber/cc-skills-golang@golang-samber-ro` skill).
— the description by samber

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

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/samber/golang-samber-lo/download
  2. Unzip 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-dev skill (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-gopls skill (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 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 lo, upgrade to lop/lom/loi only when profiling demands it

  • Error variants — most functions have Err suffixes (MapErr, FilterErr, ReduceErr) that stop on first error

Installation

go get github.com/samber/lo
PackageImportAliasGo version
Core (immutable)github.com/samber/lolo1.18+
Parallelgithub.com/samber/lo/parallellop1.18+
Mutablegithub.com/samber/lo/mutablelom1.18+
Iteratorgithub.com/samber/lo/itloi1.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.

PackageUse whenTrade-off
loDefault for all transformsAllocates new collections (safe, predictable)
lopCPU-bound work on large datasets (1000+ items)Goroutine overhead; not for I/O or small slices
lomHot path confirmed by pprof -alloc_objectsMutates input — caller must understand side effects
loiLarge datasets with chained transforms (Go 1.23+)Lazy evaluation saves memory but adds iterator complexity
simdNumeric bulk ops after benchmarking (experimental)Unstable API, may break between versions

Key rules:

  • lop is for CPU parallelism, not I/O concurrency — for I/O fan-out, use errgroup instead

  • lom breaks immutability — only use when allocation pressure is measured, never assumed

  • loi eliminates intermediate allocations in chains like Map → Filter → Take by evaluating lazily

  • For reactive/streaming pipelines over infinite event streams, → see samber/cc-skills-golang@golang-samber-ro skill + samber/ro package

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

MistakeWhy it failsFix
Using lo.Contains when slices.Contains existsUnnecessary dependency for a stdlib-covered opPrefer 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 itemsGoroutine creation overhead exceeds transform costUse lo.Map — lop benefits start at ~1000+ items for CPU-bound work
Assuming lo.Filter modifies the inputlo is immutable by default — it returns a new sliceUse lom.Filter if you explicitly need in-place mutation
Using lo.Must in production code pathsMust panics on error — fine in tests and init, dangerous in request handlersUse the non-Must variant and handle the error
Chaining many eager transforms on large dataEach step allocates an intermediate sliceUse loi (lazy iterators) to avoid intermediate allocations

Best Practices

  1. Prefer stdlib when available — slices.Contains and slices.Sort (Go 1.21+) carry no dependency; maps.Keys is Go 1.23+ and returns an iterator, so use slices.Collect(maps.Keys(m)) when you need a slice. Use lo for transforms the stdlib doesn't offer (Map, Filter, Reduce, GroupBy, Chunk, Flatten)

  2. Compose lo functions — chain lo.Filter → lo.Map → lo.GroupBy instead of writing nested loops. Each function is a building block

  3. Profile before optimizing — switch from lo to lom/lop only after go tool pprof confirms allocation or CPU as the bottleneck

  4. Use error variants — prefer lo.MapErr over lo.Map + manual error collection. Error variants stop early and propagate cleanly

  5. Use lo.Must only in tests and init — in production, handle errors explicitly

Quick Reference

FunctionWhat it does
lo.MapTransform each element
lo.Filter / lo.RejectKeep / remove elements matching predicate
lo.ReduceFold elements into a single value
lo.ForEachSide-effect iteration
lo.GroupByGroup elements by key
lo.ChunkSplit into fixed-size batches
lo.FlattenFlatten nested slices one level
lo.Uniq / lo.UniqByRemove duplicates
lo.Find / lo.FindOrElseFirst match or default
lo.Contains / lo.Every / lo.SomeMembership tests
lo.Keys / lo.ValuesExtract map keys or values
lo.PickBy / lo.OmitByFilter map entries
lo.Zip2 / lo.Unzip2Pair/unpair two slices
lo.Range / lo.RangeFromGenerate number sequences
lo.Ternary / lo.IfInline conditionals
lo.ToPtr / lo.FromPtrPointer helpers
lo.Must / lo.TryPanic-on-error / recover-as-bool
lo.Async / lo.AttemptAsync execution / retry with backoff
lo.Debounce / lo.ThrottleRate limiting
lo.ChannelDispatcherFan-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 (samber/ro 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 lom/lop

Files

evals/evals.json

{
  "skill_name": "golang-samber-lo",
  "evals": [
    {
      "id": 1,
      "name": "lop-for-io-trap",
      "prompt": "I have a Go service that needs to fetch data from 50 different REST APIs concurrently and collect results. I'm using samber/lo already. Should I use lop.Map to parallelize the HTTP calls? Write the implementation.",
      "expected_output": "Should recommend errgroup (or similar) for I/O-bound concurrency instead of lop. lop is for CPU-bound parallelism. Should explain why lop is wrong here (no context cancellation, no error handling, goroutine-per-element overhead for I/O).",
      "assertions": [
        {"text": "Recommends errgroup or similar I/O concurrency pattern instead of (or in addition to) lop for HTTP calls", "type": "semantic"},
        {"text": "Explains that lop is designed for CPU-bound parallelism, not I/O-bound work", "type": "semantic"},
        {"text": "Mentions lack of context cancellation as a limitation of lop for I/O", "type": "semantic"},
        {"text": "Does NOT simply use lop.Map as the primary solution for HTTP fan-out", "type": "semantic"},
        {"text": "Shows working Go code for the concurrent HTTP fetch pattern", "type": "semantic"}
      ]
    },
    {
      "id": 2,
      "name": "premature-lom-optimization",
      "prompt": "My Go API is a bit slow. I'm using lo.Filter and lo.Map in several places. I want to switch everything to lom.Filter and lom.Map for better performance. Can you help me refactor?",
      "expected_output": "Should advise profiling first before switching to lom. Should warn about immutability loss. Should NOT blindly refactor everything to lom.",
      "assertions": [
        {"text": "Recommends profiling (pprof, alloc_objects) before switching to lom", "type": "semantic"},
        {"text": "Warns that lom mutates the input slice (breaks immutability)", "type": "semantic"},
        {"text": "Does NOT blindly refactor all lo calls to lom without questioning the premise", "type": "semantic"},
        {"text": "Explains that the performance issue may not be caused by lo allocations", "type": "semantic"},
        {"text": "Mentions that lom is only appropriate for hot paths confirmed by profiling", "type": "semantic"},
        {"text": "Warns about concurrency safety implications of switching to mutable operations", "type": "semantic"}
      ]
    },
    {
      "id": 3,
      "name": "stdlib-vs-lo-preference",
      "prompt": "I'm writing a Go function that needs to check if a string slice contains a value, sort an int slice, and get all keys from a map. I already have samber/lo as a dependency. Should I use lo.Contains, and lo.Keys for these?",
      "expected_output": "Should recommend stdlib slices.Contains and slices.Sort over lo equivalents when using Go 1.21+. For map keys, should gate maps.Keys to Go 1.23+ and use slices.Collect(maps.Keys(m)) when a slice is needed. Should explain that stdlib is preferred for operations it covers.",
      "assertions": [
        {"text": "Recommends slices.Contains from stdlib over lo.Contains", "type": "semantic"},
        {"text": "Recommends slices.Sort or slices.SortFunc from stdlib", "type": "semantic"},
        {"text": "Recommends slices.Collect(maps.Keys(m)) from stdlib over lo.Keys when the module targets Go 1.23+", "type": "semantic"},
        {"text": "Mentions Go 1.21+ for slices helpers and Go 1.23+ for maps.Keys", "type": "semantic"},
        {"text": "Explains the rationale: prefer stdlib when it covers the operation to avoid unnecessary dependency usage", "type": "semantic"},
        {"text": "Acknowledges that lo is still useful for operations stdlib doesn't provide (Map, Filter, Reduce, GroupBy)", "type": "semantic"}
      ]
    },
    {
      "id": 4,
      "name": "loi-go-version-constraint",
      "prompt": "I'm building a data pipeline in Go 1.20 that chains multiple transformations on a large dataset (1M records). I want to use lo/it for lazy evaluation to avoid intermediate allocations. Show me how.",
      "expected_output": "Should warn that lo/it requires Go 1.23+ and cannot be used with Go 1.20. Should suggest alternatives.",
      "assertions": [
        {"text": "Warns that lo/it (loi) requires Go 1.23+ and is not available in Go 1.20", "type": "semantic"},
        {"text": "Suggests upgrading Go version to 1.23+ to use lo/it", "type": "semantic"},
        {"text": "Provides alternative approaches for Go 1.20 (e.g., compose lo functions, manual pipeline, or accept intermediate allocations)", "type": "semantic"},
        {"text": "Does NOT provide lo/it code that won't compile on Go 1.20", "type": "semantic"},
        {"text": "Mentions that loi uses range-over-func which is a Go 1.23 feature", "type": "semantic"}
      ]
    },
    {
      "id": 5,
      "name": "must-init-scope-boundary",
      "prompt": "I'm setting up a Go application. I use lo.Must in two places: (1) in main() to parse a required config file at startup, and (2) in an HTTP handler to parse each incoming request body. A teammate says both uses are wrong. Is that right?",
      "expected_output": "Should distinguish: lo.Must is acceptable in main()/init() for startup failures where panicking is appropriate (app can't run without valid config). It is NOT acceptable in HTTP handlers where panics crash the request and potentially the server. The teammate is wrong about the init use case.",
      "assertions": [
        {"text": "Correctly identifies that lo.Must in main() for startup config parsing IS acceptable", "type": "semantic"},
        {"text": "Correctly identifies that lo.Must in the HTTP handler is NOT acceptable (panics on each bad request)", "type": "semantic"},
        {"text": "Does NOT blanket-reject all uses of Must — init/startup usage is valid", "type": "semantic"},
        {"text": "Explains the reasoning: startup panics are appropriate failure modes; request panics are not", "type": "semantic"},
        {"text": "Shows proper error handling in the HTTP handler (if err != nil with http.Error response)", "type": "semantic"}
      ]
    },
    {
      "id": 6,
      "name": "import-aliases-knowledge",
      "prompt": "I want to use the parallel, mutable, and iterator sub-packages of samber/lo in my Go project. What are the correct import paths and conventional aliases?",
      "expected_output": "Should list all import paths with their conventional aliases: lop, lom, loi.",
      "assertions": [
        {"text": "Lists github.com/samber/lo/parallel with alias lop", "type": "semantic"},
        {"text": "Lists github.com/samber/lo/mutable with alias lom", "type": "semantic"},
        {"text": "Lists github.com/samber/lo/it with alias loi", "type": "semantic"},
        {"text": "Mentions that lo/it requires Go 1.23+", "type": "semantic"},
        {"text": "Lists the core package github.com/samber/lo with alias lo", "type": "semantic"}
      ]
    },
    {
      "id": 7,
      "name": "immutability-trap",
      "prompt": "I have this Go code using samber/lo:\n\nusers := []User{{Name: \"Alice\", Active: true}, {Name: \"Bob\", Active: false}}\nlo.Filter(users, func(u User, _ int) bool { return u.Active })\nfmt.Println(len(users)) // What does this print?\n\nWill the users slice be modified after the Filter call?",
      "expected_output": "Should clearly state that lo.Filter does NOT modify the input slice. The original users slice still has 2 elements. Must mention immutability-by-default.",
      "assertions": [
        {"text": "States that lo.Filter returns a NEW slice and does NOT modify the input", "type": "semantic"},
        {"text": "Correctly says len(users) still prints 2", "type": "semantic"},
        {"text": "Explains that lo is immutable by default — all core functions return new collections", "type": "semantic"},
        {"text": "Points out the bug: the return value of lo.Filter is discarded and should be assigned", "type": "semantic"},
        {"text": "Mentions lom.Filter as the alternative if in-place mutation is desired", "type": "semantic"}
      ]
    },
    {
      "id": 8,
      "name": "error-variant-awareness",
      "prompt": "I'm using samber/lo to transform a slice of URLs into responses by making HTTP calls. Some calls might fail. Currently I'm using lo.Map and collecting errors manually in a separate slice. Is there a better way?",
      "expected_output": "Should recommend lo.MapErr which stops on first error, or lo.FilterMap for skipping errors. Should explain error variant pattern.",
      "assertions": [
        {"text": "Recommends lo.MapErr as the error-aware variant of lo.Map", "type": "semantic"},
        {"text": "Explains that MapErr stops processing on the first error and returns (result, error)", "type": "semantic"},
        {"text": "Shows the MapErr function signature or usage example", "type": "semantic"},
        {"text": "Mentions that most lo functions have Err suffixes (FilterErr, ReduceErr, etc.)", "type": "semantic"},
        {"text": "Alternatively suggests lo.FilterMap if the goal is to skip errors rather than stop", "type": "semantic"}
      ]
    },
    {
      "id": 9,
      "name": "simd-production-stability",
      "prompt": "I want to use lo/exp/simd for optimizing numeric array operations in my production Go service. It processes millions of float64 values. Is this a good idea?",
      "expected_output": "Should warn that simd is experimental, API may break between versions, not covered by semver stability. Recommend benchmarking first.",
      "assertions": [
        {"text": "Warns that lo/exp/simd is experimental and API may break between versions", "type": "semantic"},
        {"text": "States it is NOT covered by semver stability guarantees", "type": "semantic"},
        {"text": "Recommends benchmarking to verify actual performance gains before adopting", "type": "semantic"},
        {"text": "Suggests version pinning if used despite experimental status", "type": "semantic"},
        {"text": "Does NOT unconditionally recommend simd for production use", "type": "semantic"}
      ]
    },
    {
      "id": 10,
      "name": "streaming-redirect-to-ro",
      "prompt": "I need to build a reactive data pipeline in Go that processes an infinite stream of events from Kafka, applies transformations, and publishes results. I'm already using samber/lo for batch transforms. Can I use lo for this streaming use case?",
      "expected_output": "Should redirect to samber/ro for reactive/streaming pipelines. Should explain that lo is for finite/batch transforms, not infinite streams.",
      "assertions": [
        {"text": "Recommends samber/ro for reactive/streaming pipelines over infinite event streams", "type": "semantic"},
        {"text": "Explains that lo is designed for finite/batch collection transforms, not infinite streams", "type": "semantic"},
        {"text": "Mentions the golang-samber-ro skill or samber/ro package by name", "type": "semantic"},
        {"text": "Does NOT attempt to use lo.Map/lo.Filter for infinite stream processing", "type": "semantic"},
        {"text": "Explains the conceptual difference: lo = batch/finite, ro = reactive/infinite", "type": "semantic"}
      ]
    },
    {
      "id": 11,
      "name": "lop-threshold-cpu-vs-io",
      "prompt": "I have two use cases in my Go service both using samber/lo. (A) I'm resizing 20 images in memory — each resize takes ~200ms of CPU. (B) I'm extracting the 'name' field from 50 user structs in memory. My teammate says I should switch both to lop for better performance. What do you think?",
      "expected_output": "Case A (image resizing): lop is appropriate — CPU-bound work, substantial per-item cost, enough items to justify goroutine overhead. Case B (field extraction): lop is wrong — trivially cheap operation on a small dataset; goroutine overhead exceeds benefit. The teammate is only right about case A.",
      "assertions": [
        {"text": "Approves lop.Map for case A (CPU-bound image resizing with ~200ms per item)", "type": "semantic"},
        {"text": "Rejects lop.Map for case B (trivial field extraction on 50 items)", "type": "semantic"},
        {"text": "Distinguishes CPU-bound work (lop appropriate) from trivial/cheap operations (lo sufficient)", "type": "semantic"},
        {"text": "Mentions that lop overhead only pays off for CPU-bound work on datasets of ~1000+ items OR expensive per-item operations", "type": "semantic"},
        {"text": "Does NOT recommend lop for both use cases indiscriminately", "type": "semantic"}
      ]
    },
    {
      "id": 12,
      "name": "filtermap-vs-maperr-for-partial-failures",
      "prompt": "I have a []string of user-supplied date strings. I need to parse each one with time.Parse, keep the successfully parsed dates, and silently discard parse failures (not stop on first error). I'm using samber/lo. What's the right approach?",
      "expected_output": "Should recommend lo.FilterMap (not lo.MapErr which stops on first error, and not lo.Filter+lo.Map which creates an intermediate slice). FilterMap maps and keeps only successful results in a single pass. The key trap is that MapErr stops on the first error, which is the opposite of what's wanted here.",
      "assertions": [
        {"text": "Recommends lo.FilterMap for map-and-discard-failures in a single pass", "type": "semantic"},
        {"text": "Does NOT recommend lo.MapErr (which stops on first error, not what's wanted)", "type": "semantic"},
        {"text": "Shows FilterMap with a (time.Time, bool) return where bool is false on parse failure", "type": "semantic"},
        {"text": "Explains that FilterMap silently discards items where the bool is false", "type": "semantic"},
        {"text": "Does NOT chain lo.Filter + lo.Map as the primary solution (creates intermediate slice)", "type": "semantic"}
      ]
    },
    {
      "id": 13,
      "name": "channel-dispatcher-load-balancing-strategy",
      "prompt": "I have a Go service that distributes tasks to 4 worker goroutines via channels. Workers have different processing speeds — some tasks go to a fast worker (handles 3x more), others to slower workers. I'm using samber/lo and already know about lo.ChannelDispatcher. Which dispatch strategy should I use so that faster workers receive proportionally more tasks?",
      "expected_output": "Should recommend WeightedRandom strategy. RoundRobin ignores worker speed. Random is uniform. WeightedRandom lets you assign relative weights matching worker capacity. Should show how to configure weights.",
      "assertions": [
        {"text": "Recommends the WeightedRandom dispatch strategy (not RoundRobin or Random)", "type": "semantic"},
        {"text": "Explains that RoundRobin distributes evenly regardless of worker capacity", "type": "semantic"},
        {"text": "Explains that WeightedRandom allows assigning proportional weights to each output channel", "type": "semantic"},
        {"text": "Shows lo.ChannelDispatcher usage with the WeightedRandom strategy and weights", "type": "semantic"},
        {"text": "Does NOT recommend RoundRobin as the primary solution for unequal-capacity workers", "type": "semantic"},
        {"text": "Shows or describes setting weights where the fast worker gets 3x the weight of slow workers", "type": "semantic"}
      ]
    },
    {
      "id": 14,
      "name": "v2-version-trap",
      "prompt": "I want to upgrade my project from samber/lo v1 to v2 for the latest features. What's the migration path? Are there breaking changes?",
      "expected_output": "Should clarify that there is no v2 of samber/lo. The library is on v1 with semver stability guarantees.",
      "assertions": [
        {"text": "States that samber/lo v2 does not exist — the library is on v1", "type": "semantic"},
        {"text": "Mentions that v1 follows semantic versioning with no breaking changes before v2", "type": "semantic"},
        {"text": "Provides the correct install command: go get github.com/samber/lo@v1", "type": "semantic"},
        {"text": "Does NOT fabricate v2 migration steps or breaking changes", "type": "semantic"}
      ]
    },
    {
      "id": 15,
      "name": "lazy-chain-intermediate-allocations",
      "prompt": "I have a pipeline in Go that processes 1M records: filter by status, map to extract fields, group by category, then take the top 10 from each group. Using samber/lo, each step creates an intermediate slice. How can I avoid these intermediate allocations?",
      "expected_output": "Should recommend lo/it (loi) for lazy evaluation to eliminate intermediate allocations. Should explain the lazy pipeline pattern.",
      "assertions": [
        {"text": "Recommends lo/it (loi) for lazy evaluation to avoid intermediate slice allocations", "type": "semantic"},
        {"text": "Explains that loi pipelines process elements on-demand without buffering intermediate results", "type": "semantic"},
        {"text": "Mentions Go 1.23+ requirement for loi", "type": "semantic"},
        {"text": "Shows or describes a lazy pipeline using loi functions", "type": "semantic"},
        {"text": "Contrasts eager (lo) vs lazy (loi) approach in terms of memory allocation", "type": "semantic"}
      ]
    },
    {
      "id": 16,
      "name": "lo-zero-dependencies",
      "prompt": "My team is concerned about adding samber/lo as a dependency. They worry about transitive dependencies and supply chain risk. What dependencies does samber/lo pull in?",
      "expected_output": "Should state that samber/lo has zero external runtime dependencies — it relies only on Go's standard library.",
      "assertions": [
        {"text": "States that samber/lo has zero external/runtime dependencies", "type": "semantic"},
        {"text": "Mentions it relies only on Go's standard library", "type": "semantic"},
        {"text": "Addresses the supply chain concern by noting minimal transitive dependency risk", "type": "semantic"},
        {"text": "Does NOT claim lo has external dependencies", "type": "semantic"}
      ]
    },
    {
      "id": 17,
      "name": "ternary-side-effect-ordering",
      "prompt": "I'm refactoring a Go function to use samber/lo for conciseness. I have this code:\n\n```go\nvar label string\nif isAdmin {\n    label = formatAdminLabel(user) // calls DB, expensive\n} else {\n    label = user.Name\n}\n```\n\nI rewrote it as:\n\n```go\nlabel := lo.Ternary(isAdmin, formatAdminLabel(user), user.Name)\n```\n\nMy colleague says this is a bug. Are they right?",
      "expected_output": "Yes, the colleague is right. lo.Ternary is a regular Go function call — both arguments are evaluated before the function is called. formatAdminLabel(user) runs unconditionally even when isAdmin is false. Should recommend lo.TernaryF with closures so only the winning branch executes.",
      "assertions": [
        {"text": "Confirms the colleague is correct — this is indeed a bug", "type": "semantic"},
        {"text": "Explains that lo.Ternary evaluates BOTH branches before the function is called (Go's eager argument evaluation)", "type": "semantic"},
        {"text": "Identifies that formatAdminLabel(user) runs even when isAdmin is false", "type": "semantic"},
        {"text": "Recommends lo.TernaryF with closures: lo.TernaryF(isAdmin, func() string { return formatAdminLabel(user) }, func() string { return user.Name })", "type": "semantic"}
      ]
    }
  ]
}

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