mcpField
G
golang-samber-lo

golang-samber-lo

github.com/samber开发3.7k38.9k 次安装5 天前更新
代码仓库

关于 golang-samber-lo

介绍 samber/lo 的 Go 技能;该库基于泛型,提供声明式集合转换及常用操作,帮助工程师选择合适的函数和扩展包,并说明何时优先使用标准库。

主要功能

  1. 01切片与映射的泛型函数
  2. 02转换、筛选、归约与分组数据
  3. 03返回错误的函数变体
  4. 04并行、可变与迭代器包
  5. 05标准库选择与性能分析指南

适用场景

  1. 01替代繁琐的集合循环代码
  2. 02组合数据转换流水线
  3. 03分析性能后选择惰性或并行操作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-lo

安装后在 Claude Code 中输入/golang-samber-lo确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
advanced-patterns.md
api-reference.md
package-guide.md

详细介绍

角色: 你是一名 Go 工程师,更喜欢使用声明式集合转换,而不是手动编写循环。你会使用 lo 来消除样板代码,但也知道什么时候标准库就够用,什么时候该升级到 lop、lom 或 loi。

samber/lo — Go 函数式工具库

受 Lodash 启发、以泛型为先的工具库,提供 500 多个类型安全的辅助函数,涵盖切片、映射、字符串、数学、通道、元组和并发。零外部依赖。默认不可变。

官方资源:

本技能并未涵盖所有内容,更多信息请参阅库文档和代码示例:

  • 如需查看 Go 包文档、符号、版本、导入方和已知漏洞,→ 请参阅 samber/cc-skills-golang@golang-pkg-go-dev 技能(godig),查询 Go 包信息时优先于 Context7。
  • 如需在自己的代码中了解此库的用法(定义、调用位置、诊断信息),→ 请参阅 samber/cc-skills-golang@golang-gopls 技能(gopls)。
  • 对于未收录在 pkg.go.dev 上的文档,可将 Context7 作为备用方案。

为什么选择 samber/lo

Go 标准库的 slices 和 maps 包涵盖约 10 个基本辅助函数(排序、包含判断、键)。其他所有操作——Map、Filter、Reduce、GroupBy、Chunk、Flatten、Zip——都需要手动编写 for 循环。lo 填补了这一空白:

  • 类型安全的泛型 — 无需 interface{} 类型转换,无需反射,可在编译时检查,无接口装箱开销
  • 默认不可变 — 返回新的集合,可安全并发读取,更易于理解
  • 可组合 — 函数接收并返回切片/映射,因此可以直接串联,无需包装类型
  • 零依赖 — 仅使用 Go 标准库,无传递依赖风险
  • 渐进式复杂度 — 从 lo 开始,仅在性能分析表明有需要时才升级到 lop/lom/loi
  • 错误变体 — 大多数函数都有带 Err 后缀的版本(MapErr、FilterErr、ReduceErr),遇到第一个错误时即停止

安装

go get github.com/samber/lo
包导入路径别名Go 版本
核心(不可变)github.com/samber/lolo1.18+
并行github.com/samber/lo/parallellop1.18+
可变github.com/samber/lo/mutablelom1.18+
迭代器github.com/samber/lo/itloi1.23+
SIMD(实验性)github.com/samber/lo/exp/simd—1.25+(仅限 amd64)

选择合适的包

从 lo 开始。只有在性能分析显示存在瓶颈,或明确需要惰性求值时,才使用其他包。

包适用场景权衡
lo所有转换的默认选择会分配新集合(安全、可预测)
lop大型数据集(1000 多项)的 CPU 密集型工作有 goroutine 开销;不适用于 I/O 或小型切片
lom通过 pprof -alloc_objects 确认存在热点路径会修改输入 — 调用方必须了解副作用
loi使用串联转换处理大型数据集(Go 1.23+)惰性求值可节省内存,但会增加迭代器复杂度
simd基准测试后用于数值批量操作(实验性)API 不稳定,版本更新间可能出现破坏性变更

关键规则:

  • lop 用于 CPU 并行,而不是 I/O 并发 — 对于 I/O 扇出,请改用 errgroup
  • lom 会破坏不可变性 — 仅在测得分配压力时使用,切勿想当然地使用
  • 对 Map → Filter → Take 这样的链式操作,loi 通过惰性求值消除中间分配
  • 对无限事件流进行响应式/流式处理时,→ 请参阅 samber/cc-skills-golang@golang-samber-ro 技能和 samber/ro 包

有关详细的包对比和决策流程图,请参阅包指南。

核心模式

转换切片
// ✓ 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)
}
过滤 + 归约
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": [...]}
错误变体 — 遇到第一个错误时停止
results, err := lo.MapErr(urls, func(url string, _ int) (Response, error) {
    return http.Get(url)
})

常见错误

错误失败原因修正方法
在 slices.Contains 已存在时使用 lo.Contains标准库已涵盖此操作,无需引入依赖Go 1.21+ 优先使用 slices.Contains/slices.Sort;需要键切片时,Go 1.23+ 使用 slices.Collect(maps.Keys(m))
对 10 个元素使用 lop.Map创建 Goroutine 的开销超过转换成本使用 lo.Map——对于 CPU 密集型工作,lop 从约 1000 个元素起才有优势
认为 lo.Filter 会修改输入lo 默认不可变——它会返回一个新切片如果确实需要原地修改,请使用 lom.Filter
在生产代码路径中使用 lo.MustMust 遇到错误会触发 panic——在测试和初始化代码中没问题,但在请求处理程序中很危险使用非 Must 变体并处理错误
在大型数据上连续执行多个急切转换每一步都会分配一个中间切片使用 loi(惰性迭代器)以避免分配中间切片

最佳实践

  1. 有标准库可用时优先使用标准库——slices.Contains 和 slices.Sort(Go 1.21+)无需依赖;maps.Keys 需要 Go 1.23+,并返回一个迭代器,因此需要切片时请使用 slices.Collect(maps.Keys(m))。对于标准库未提供的转换(Map、Filter、Reduce、GroupBy、Chunk、Flatten),请使用 lo
  2. 组合使用 lo 函数——将 lo.Filter → lo.Map → lo.GroupBy 串联起来,而不是编写嵌套循环。每个函数都是一个构建模块
  3. 先分析性能,再优化——只有在 go tool pprof 确认分配或 CPU 是瓶颈后,才从 lo 切换到 lom/lop
  4. 使用错误处理变体——优先使用 lo.MapErr,而不是 lo.Map 加手动收集错误。错误处理变体会提前停止并妥善传递错误
  5. 仅在测试和初始化代码中使用 lo.Must——在生产环境中,应显式处理错误

快速参考

函数功能
lo.Map转换每个元素
lo.Filter / lo.Reject保留 / 移除符合谓词条件的元素
lo.Reduce将元素折叠为单个值
lo.ForEach执行带副作用的迭代
lo.GroupBy按键对元素分组
lo.Chunk将元素拆分为固定大小的批次
lo.Flatten将嵌套切片展平一层
lo.Uniq / lo.UniqBy移除重复项
lo.Find / lo.FindOrElse查找第一个匹配项或返回默认值
lo.Contains / lo.Every / lo.Some成员测试
lo.Keys / lo.Values提取映射的键或值
lo.PickBy / lo.OmitBy筛选映射条目
lo.Zip2 / lo.Unzip2将两个切片配对 / 拆分配对
lo.Range / lo.RangeFrom生成数字序列
lo.Ternary / lo.If内联条件表达式
lo.ToPtr / lo.FromPtr指针辅助函数
lo.Must / lo.Try遇错触发 panic / 将错误恢复为布尔值
lo.Async / lo.Attempt异步执行 / 带退避的重试
lo.Debounce / lo.Throttle速率限制
lo.ChannelDispatcher将消息分发到多个通道

完整函数目录(300 多个函数)请参阅 API 参考。

有关组合模式、标准库互操作和迭代器流水线,请参阅 高级模式。

如果您在 samber/lo 中遇到 Bug 或意外行为,请在 github.com/samber/lo/issues 提交问题。

交叉引用

  • → 有关对无限事件流进行响应式 / 流式处理的流水线,请参阅 samber/cc-skills-golang@golang-samber-ro skill(samber/ro 包)
  • → 有关可与 lo 转换组合使用的单子类型(Option、Result、Either),请参阅 samber/cc-skills-golang@golang-samber-mo skill
  • → 有关如何选择合适的底层数据结构,请参阅 samber/cc-skills-golang@golang-data-structures skill
  • → 有关切换到 lom/lop 前的性能分析方法,请参阅 samber/cc-skills-golang@golang-performance skill

评论

支持 Markdown