{"id":"b8380505-2cac-41d7-bdae-d99f2b4a2de4","shortId":"ySbCHN","kind":"skill","title":"golang-samber-lo","tagline":"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/p","description":"**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`.\n\n# samber/lo — Functional Utilities for Go\n\nLodash-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.\n\n**Official Resources:**\n\n- [github.com/samber/lo](https://github.com/samber/lo)\n- [lo.samber.dev](https://lo.samber.dev)\n- [pkg.go.dev/github.com/samber/lo](https://pkg.go.dev/github.com/samber/lo)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.\n\n## Why samber/lo\n\nGo'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:\n\n- **Type-safe generics** — no `interface{}` casts, no reflection, compile-time checking, no interface boxing overhead\n- **Immutable by default** — returns new collections, safe for concurrent reads, easier to reason about\n- **Composable** — functions take and return slices/maps, so they chain without wrapper types\n- **Zero dependencies** — only Go stdlib, no transitive dependency risk\n- **Progressive complexity** — start with `lo`, upgrade to `lop`/`lom`/`loi` only when profiling demands it\n- **Error variants** — most functions have `Err` suffixes (`MapErr`, `FilterErr`, `ReduceErr`) that stop on first error\n\n## Installation\n\n```bash\ngo get github.com/samber/lo\n```\n\n| Package | Import | Alias | Go version |\n| --- | --- | --- | --- |\n| Core (immutable) | `github.com/samber/lo` | `lo` | 1.18+ |\n| Parallel | `github.com/samber/lo/parallel` | `lop` | 1.18+ |\n| Mutable | `github.com/samber/lo/mutable` | `lom` | 1.18+ |\n| Iterator | `github.com/samber/lo/it` | `loi` | 1.23+ |\n| SIMD (experimental) | `github.com/samber/lo/exp/simd` | — | 1.25+ (amd64 only) |\n\n## Choose the Right Package\n\nStart with `lo`. Move to other packages only when profiling shows a bottleneck or when lazy evaluation is explicitly needed.\n\n| Package | Use when | Trade-off |\n| --- | --- | --- |\n| `lo` | Default for all transforms | Allocates new collections (safe, predictable) |\n| `lop` | CPU-bound work on large datasets (1000+ items) | Goroutine overhead; not for I/O or small slices |\n| `lom` | Hot path confirmed by `pprof -alloc_objects` | Mutates input — caller must understand side effects |\n| `loi` | Large datasets with chained transforms (Go 1.23+) | Lazy evaluation saves memory but adds iterator complexity |\n| `simd` | Numeric bulk ops after benchmarking (experimental) | Unstable API, may break between versions |\n\n**Key rules:**\n\n- `lop` is for CPU parallelism, not I/O concurrency — for I/O fan-out, use `errgroup` instead\n- `lom` breaks immutability — only use when allocation pressure is measured, never assumed\n- `loi` eliminates intermediate allocations in chains like `Map → Filter → Take` by evaluating lazily\n- For reactive/streaming pipelines over infinite event streams, → see `samber/cc-skills-golang@golang-samber-ro` skill + `samber/ro` package\n\nFor detailed package comparison and decision flowchart, see [Package Guide](./references/package-guide.md).\n\n## Core Patterns\n\n### Transform a slice\n\n```go\n// ✓ lo — declarative, type-safe\nnames := lo.Map(users, func(u User, _ int) string {\n    return u.Name\n})\n\n// ✗ Manual — boilerplate, error-prone\nnames := make([]string, 0, len(users))\nfor _, u := range users {\n    names = append(names, u.Name)\n}\n```\n\n### Filter + Reduce\n\n```go\ntotal := lo.Reduce(\n    lo.Filter(orders, func(o Order, _ int) bool {\n        return o.Status == \"paid\"\n    }),\n    func(sum float64, o Order, _ int) float64 {\n        return sum + o.Amount\n    },\n    0,\n)\n```\n\n### GroupBy\n\n```go\nbyStatus := lo.GroupBy(tasks, func(t Task, _ int) string {\n    return t.Status\n})\n// map[string][]Task{\"open\": [...], \"closed\": [...]}\n```\n\n### Error variant — stop on first error\n\n```go\nresults, err := lo.MapErr(urls, func(url string, _ int) (Response, error) {\n    return http.Get(url)\n})\n```\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| Using `lo.Contains` when `slices.Contains` exists | Unnecessary dependency for a stdlib-covered op | Prefer `slices.Contains`, `slices.Sort`, `maps.Keys` since Go 1.21+ |\n| 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 |\n| 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 |\n| 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 |\n| Chaining many eager transforms on large data | Each step allocates an intermediate slice | Use `loi` (lazy iterators) to avoid intermediate allocations |\n\n## Best Practices\n\n1. **Prefer stdlib when available** — `slices.Contains`, `slices.Sort`, `maps.Keys` carry no dependency. Use `lo` for transforms the stdlib doesn't offer (Map, Filter, Reduce, GroupBy, Chunk, Flatten)\n2. **Compose lo functions** — chain `lo.Filter` → `lo.Map` → `lo.GroupBy` instead of writing nested loops. Each function is a building block\n3. **Profile before optimizing** — switch from `lo` to `lom`/`lop` only after `go tool pprof` confirms allocation or CPU as the bottleneck\n4. **Use error variants** — prefer `lo.MapErr` over `lo.Map` + manual error collection. Error variants stop early and propagate cleanly\n5. **Use `lo.Must` only in tests and init** — in production, handle errors explicitly\n\n## Quick Reference\n\n| Function | What it does |\n| --- | --- |\n| `lo.Map` | Transform each element |\n| `lo.Filter` / `lo.Reject` | Keep / remove elements matching predicate |\n| `lo.Reduce` | Fold elements into a single value |\n| `lo.ForEach` | Side-effect iteration |\n| `lo.GroupBy` | Group elements by key |\n| `lo.Chunk` | Split into fixed-size batches |\n| `lo.Flatten` | Flatten nested slices one level |\n| `lo.Uniq` / `lo.UniqBy` | Remove duplicates |\n| `lo.Find` / `lo.FindOrElse` | First match or default |\n| `lo.Contains` / `lo.Every` / `lo.Some` | Membership tests |\n| `lo.Keys` / `lo.Values` | Extract map keys or values |\n| `lo.PickBy` / `lo.OmitBy` | Filter map entries |\n| `lo.Zip2` / `lo.Unzip2` | Pair/unpair two slices |\n| `lo.Range` / `lo.RangeFrom` | Generate number sequences |\n| `lo.Ternary` / `lo.If` | Inline conditionals |\n| `lo.ToPtr` / `lo.FromPtr` | Pointer helpers |\n| `lo.Must` / `lo.Try` | Panic-on-error / recover-as-bool |\n| `lo.Async` / `lo.Attempt` | Async execution / retry with backoff |\n| `lo.Debounce` / `lo.Throttle` | Rate limiting |\n| `lo.ChannelDispatcher` | Fan-out to multiple channels |\n\nFor the complete function catalog (300+ functions), see [API Reference](./references/api-reference.md).\n\nFor composition patterns, stdlib interop, and iterator pipelines, see [Advanced Patterns](./references/advanced-patterns.md).\n\nIf you encounter a bug or unexpected behavior in samber/lo, open an issue at [github.com/samber/lo/issues](https://github.com/samber/lo/issues).\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-samber-ro` skill for reactive/streaming pipelines over infinite event streams (`samber/ro` package)\n- → See `samber/cc-skills-golang@golang-samber-mo` skill for monadic types (Option, Result, Either) that compose with lo transforms\n- → See `samber/cc-skills-golang@golang-data-structures` skill for choosing the right underlying data structure\n- → See `samber/cc-skills-golang@golang-performance` skill for profiling methodology before switching to `lom`/`lop`","tags":["golang","samber","skills","agent","agent-skills","antigravity","claude","claude-code","code","codex","coding","copilot"],"capabilities":["skill","source-samber","skill-golang-samber-lo","topic-agent","topic-agent-skills","topic-antigravity","topic-claude","topic-claude-code","topic-code","topic-codex","topic-coding","topic-copilot","topic-cursor","topic-gemini","topic-gemini-cli-extension"],"categories":["cc-skills-golang"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/samber/cc-skills-golang/golang-samber-lo","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add samber/cc-skills-golang","source_repo":"https://github.com/samber/cc-skills-golang","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 1725 github stars · SKILL.md body (7,920 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:02.294Z","embedding":null,"createdAt":"2026-04-18T20:32:46.189Z","updatedAt":"2026-05-18T18:53:02.294Z","lastSeenAt":"2026-05-18T18:53:02.294Z","tsv":"'/github.com/samber/lo](https://pkg.go.dev/github.com/samber/lo)':124 '/references/advanced-patterns.md':952 '/references/api-reference.md':940 '/references/package-guide.md':480 '/samber/lo':270,280 '/samber/lo/exp/simd':305 '/samber/lo/issues](https://github.com/samber/lo/issues).':969 '/samber/lo/it':298 '/samber/lo/mutable':292 '/samber/lo/parallel':286 '/samber/lo](https://github.com/samber/lo)':119 '0':510,546 '1':712 '1.18':282,288,294 '1.21':610 '1.23':300,389 '1.25':306 '10':158,614 '1000':357,628 '2':738 '3':757 '300':935 '4':779 '5':797 '500':12,95 'add':395 'advanc':950 'alia':273 'alloc':344,373,435,444,698,709,773 'amd64':307 'api':406,938 'append':518 'assum':440,635 'async':914 'avail':716 'avoid':707 'backoff':918 'bash':265 'basic':159 'batch':850 'behavior':960 'benchmark':403 'benefit':625 'best':710 'block':756 'boilerpl':63,503 'bool':532,911 'bottleneck':325,778 'bound':352,633 'box':197 'break':408,430 'bug':957 'build':755 'bulk':400 'bystatus':549 'caller':377 'carri':720 'cast':188 'catalog':934 'chain':221,386,446,689,742 'channel':21,105,929 'check':194 'choos':309,1015 'chunk':31,170,736 'clean':796 'close':563 'code':136,664 'collect':52,204,346,789 'common':584 'comparison':473 'compil':192 'compile-tim':191 'complet':932 'complex':235,397 'compos':213,739,1003 'composit':942 'concurr':26,40,108,207,420 'condit':897 'confirm':370,772 'contain':162 'context7':141 'core':36,276,481 'cost':621 'cover':157,602 'cpu':351,416,632,775 'cpu-bound':350,631 'creation':617 'cross':971 'cross-refer':970 'danger':675 'data':695,1011,1019 'dataset':356,384 'decis':475 'declar':51,488 'default':114,201,340,644,866 'demand':247 'depend':111,226,232,597,722 'detail':471 'discover':146 'document':134 'doesn':729 'duplic':860 'eager':691 'earli':793 'easier':209 'effect':381,837 'either':1001 'element':819,824,829,841 'elimin':62,442 'els':165 'encount':955 'engin':48 'enough':71 'entri':883 'err':254,572 'errgroup':427 'error':249,263,505,564,569,580,669,688,781,788,790,808,907 'error-pron':504 'etc':35 'evalu':329,391,452 'event':459,985 'everyth':164 'exampl':137 'exceed':619 'execut':915 'exhaust':129 'exist':595 'experiment':302,404 'explicit':331,654,809 'extern':110 'extract':874 'fail':589 'fan':424,925 'fan-out':423,924 'fill':179 'filter':28,167,449,521,733,881 'filtererr':257 'find':33 'fine':670 'first':91,262,568,863 'fix':590,848 'fixed-s':847 'flatten':32,171,737,852 'float64':538,542 'flowchart':476 'fold':828 'for-loop':175 'func':495,528,536,552,575 'function':5,17,82,214,252,741,752,812,933,936 'gap':181 'generat':891 'generic':16,90,185 'generics-first':89 'get':267 'github.com':118,269,279,285,291,297,304,968 'github.com/samber/lo':268,278 'github.com/samber/lo/exp/simd':303 'github.com/samber/lo/issues](https://github.com/samber/lo/issues).':967 'github.com/samber/lo/it':296 'github.com/samber/lo/mutable':290 'github.com/samber/lo/parallel':284 'github.com/samber/lo](https://github.com/samber/lo)':117 'go':47,85,150,228,266,274,388,486,523,548,570,609,769 'golang':2,9,464,976,992,1010,1024 'golang-data-structur':1009 'golang-perform':1023 'golang-samber-lo':1 'golang-samber-mo':991 'golang-samber-ro':463,975 'goroutin':359,616 'group':840 'groupbi':30,169,547,735 'guid':479 'handl':686,807 'handler':678 'help':143 'helper':7,99,160,901 'hot':368 'http.get':582 'i/o':363,419,422 'immut':37,112,199,277,431,642 'import':272 'in-plac':656 'infinit':458,984 'inform':140 'init':674,804 'inlin':896 'input':376,639 'inspir':88 'instal':264 'instead':428,746 'int':498,531,541,555,578 'interfac':187,196 'intermedi':443,700,708 'interop':945 'issu':965 'item':358,615,629 'iter':295,396,705,838,947 'keep':822 'key':163,411,843,876 'know':66 'larg':355,383,694 'lazi':328,390,704 'lazili':453 'len':511 'level':856 'librari':93,133 'like':447 'limit':922 'lo':4,39,60,178,238,281,315,339,487,640,724,740,763,1005 'lo.async':912 'lo.attempt':913 'lo.channeldispatcher':923 'lo.chunk':844 'lo.contains':592,867 'lo.debounce':919 'lo.every':868 'lo.filter':526,636,743,820 'lo.find':861 'lo.findorelse':862 'lo.flatten':851 'lo.foreach':834 'lo.fromptr':899 'lo.groupby':550,745,839 'lo.if':895 'lo.keys':872 'lo.map':493,623,744,786,816 'lo.maperr':573,784 'lo.must':661,799,902 'lo.omitby':880 'lo.pickby':879 'lo.range':889 'lo.rangefrom':890 'lo.reduce':525,827 'lo.reject':821 'lo.samber.dev':120,121 'lo.some':869 'lo.ternary':894 'lo.throttle':920 'lo.toptr':898 'lo.try':903 'lo.uniq':857 'lo.uniqby':858 'lo.unzip2':885 'lo.values':873 'lo.zip2':884 'lo/p':42 'lodash':87 'lodash-inspir':86 'loi':80,243,299,382,441,703 'lom':78,242,293,367,429,765,1033 'lom.filter':651 'loop':56,177,750 'lop':77,241,287,349,413,624,766,1034 'lop.map':612 'make':508 'mani':690 'manual':55,174,502,787 'map':20,27,102,155,166,448,559,732,875,882 'maperr':256 'maps.keys':607,719 'match':825,864 'math':23,104 'may':407 'measur':438 'membership':870 'memori':393 'methodolog':1029 'mistak':585,586 'mo':994 'modifi':637 'monad':997 'move':316 'multipl':928 'must':378,666,683 'mutabl':289 'mutat':375,659 'name':492,507,517,519 'need':332,655 'nest':749,853 'never':439 'new':203,345,648 'non':682 'non-must':681 'number':892 'numer':399 'o':529,539 'o.amount':545 'o.status':534 'object':374 'offer':731 'offici':115 'one':855 'op':401,603 'open':562,963 'optim':760 'option':999 'order':527,530,540 'overhead':198,360,618 'packag':38,156,271,312,319,333,469,472,478,988 'paid':535 'pair/unpair':886 'panic':667,905 'panic-on-error':904 'parallel':283,417 'path':369,665 'pattern':482,943,951 'perform':1025 'persona':43 'pipelin':456,948,982 'pkg.go.dev':123 'pkg.go.dev/github.com/samber/lo](https://pkg.go.dev/github.com/samber/lo)':122 'place':658 'platform':147 'pleas':130 'pointer':900 'pprof':372,771 'practic':711 'predic':826 'predict':348 'prefer':50,604,713,783 'pressur':436 'product':663,806 'profil':246,322,758,1028 'program':6 'progress':234 'prone':506 'propag':795 'quick':810 'rang':515 'rate':921 'reach':58 'reactive/streaming':455,981 'read':208 'reason':211 'recov':909 'recover-as-bool':908 'reduc':29,168,522,734 'reduceerr':258 'refer':131,811,939,972 'reflect':190 'remov':823,859 'request':677 'requir':173 'resourc':116 'respons':579 'result':571,1000 'retri':916 'return':202,217,500,533,543,557,581,646 'right':311,1017 'risk':233 'ro':466,978 'rule':412 'safe':15,98,184,205,347,491 'samber':3,465,977,993 'samber/cc-skills-golang':462,974,990,1008,1022 'samber/lo':11,81,149,962 'samber/ro':468,987 'save':392 'see':461,477,937,949,973,989,1007,1021 'sequenc':893 'show':323 'side':380,836 'side-effect':835 'simd':301,398 'sinc':608 'singl':832 'size':849 'skill':126,467,979,995,1013,1026 'skill-golang-samber-lo' 'slice':19,101,153,366,485,649,701,854,888 'slices.contains':594,605,717 'slices.sort':606,718 'slices/maps':218 'small':365 'sort':161 'source-samber' 'split':845 'start':236,313,626 'stdlib':69,152,229,601,714,728,944 'stdlib-cov':600 'step':697 'stop':260,566,792 'stream':460,986 'string':22,103,499,509,556,560,577 'structur':1012,1020 'suffix':255 'sum':537,544 'switch':761,1031 't.status':558 'take':215,450 'task':551,554,561 'test':672,802,871 'time':193 'tool':770 'topic-agent' 'topic-agent-skills' 'topic-antigravity' 'topic-claude' 'topic-claude-code' 'topic-code' 'topic-codex' 'topic-coding' 'topic-copilot' 'topic-cursor' 'topic-gemini' 'topic-gemini-cli-extension' 'total':524 'trade':337 'trade-off':336 'transform':53,343,387,483,620,692,726,817,1006 'transit':231 'tupl':24,106 'two':887 'type':14,97,183,224,490,998 'type-saf':13,96,182,489 'u':496,514 'u.name':501,520 'under':1018 'understand':379 'unexpect':959 'uniq':34 'unnecessari':596 'unstabl':405 'upgrad':75,239 'url':574,576,583 'use':10,334,426,433,591,611,622,650,660,679,702,723,780,798 'user':494,497,512,516 'util':83,92 'valu':833,878 'variant':41,250,565,684,782,791 'version':275,410 'without':222 'work':353,634 'wrapper':223 'write':748 'zero':109,225 'zip':172","prices":[{"id":"2153683e-f48e-4fe0-b76b-379af26bfbf6","listingId":"b8380505-2cac-41d7-bdae-d99f2b4a2de4","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"samber","category":"cc-skills-golang","install_from":"skills.sh"},"createdAt":"2026-04-18T20:32:46.189Z"}],"sources":[{"listingId":"b8380505-2cac-41d7-bdae-d99f2b4a2de4","source":"github","sourceId":"samber/cc-skills-golang/golang-samber-lo","sourceUrl":"https://github.com/samber/cc-skills-golang/tree/main/skills/golang-samber-lo","isPrimary":false,"firstSeenAt":"2026-04-18T21:55:19.361Z","lastSeenAt":"2026-05-18T18:53:02.294Z"},{"listingId":"b8380505-2cac-41d7-bdae-d99f2b4a2de4","source":"skills_sh","sourceId":"samber/cc-skills-golang/golang-samber-lo","sourceUrl":"https://skills.sh/samber/cc-skills-golang/golang-samber-lo","isPrimary":true,"firstSeenAt":"2026-04-18T20:32:46.189Z","lastSeenAt":"2026-05-07T22:40:28.289Z"}],"details":{"listingId":"b8380505-2cac-41d7-bdae-d99f2b4a2de4","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"samber","slug":"golang-samber-lo","github":{"repo":"samber/cc-skills-golang","stars":1725,"topics":["agent","agent-skills","ai","antigravity","claude","claude-code","code","codex","coding","copilot","cursor","gemini","gemini-cli-extension","openclaw","opencode","plugin","skills","skillsmp","vibe-coding"],"license":"mit","html_url":"https://github.com/samber/cc-skills-golang","pushed_at":"2026-05-18T17:36:00Z","description":"🧑‍🎨 A collection of Golang agentic skills that works","skill_md_sha":"7597f0424556f415f446804d7378035510c09bbd","skill_md_path":"skills/golang-samber-lo/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/samber/cc-skills-golang/tree/main/skills/golang-samber-lo"},"layout":"multi","source":"github","category":"cc-skills-golang","frontmatter":{"name":"golang-samber-lo","license":"MIT","description":"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 golang-samber-ro skill).","compatibility":"Designed for Claude Code or similar AI coding agents, and for projects using Golang."},"skills_sh_url":"https://skills.sh/samber/cc-skills-golang/golang-samber-lo"},"updatedAt":"2026-05-18T18:53:02.294Z"}}