
golang-samber-lo
熱門Golang 的函數式程式設計輔助工具,使用 samber/lo — 500+ 個型別安全的泛型函式,用於切片、映射、通道、字串、數學、元組和並發(Map、Filter、Reduce、GroupBy、Chunk、Flatten、Find、Uniq 等)。核心不可變套件 (lo)、並發變體 (lo/parallel 別名 lop)、原地變異 (lo/mutable 別名 lom)、惰性迭代器 (lo/it 別名 loi,適用於 Go 1.23+),以及實驗性 SIMD (lo/exp/simd)。適用於使用或採用 samber/lo 時、程式碼庫匯入 github.com/samber/lo 時,或在 Go 中實作函數式資料轉換時。不適用於串流管線(→ 請參閱 `samber/cc-skills-golang@golang-samber-ro` 技能)。
Golang 的函數式程式設計輔助工具,使用 samber/lo — 500+ 個型別安全的泛型函式,用於切片、映射、通道、字串、數學、元組和並發(Map、Filter、Reduce、GroupBy、Chunk、Flatten、Find、Uniq 等)。核心不可變套件 (lo)、並發變體 (lo/parallel 別名 lop)、原地變異 (lo/mutable 別名 lom)、惰性迭代器 (lo/it 別名 loi,適用於 Go 1.23+),以及實驗性 SIMD (lo/exp/simd)。適用於使用或採用 samber/lo 時、程式碼庫匯入 github.com/samber/lo 時,或在 Go 中實作函數式資料轉換時。不適用於串流管線(→ 請參閱 `samber/cc-skills-golang@golang-samber-ro` 技能)。
角色設定: 你是一位偏好使用宣告式集合轉換而非手動迴圈的 Go 工程師。你會使用 lo 來消除樣板程式碼,但你知道何時標準函式庫已足夠,以及何時該升級到 lop、lom 或 loi。
samber/lo — Go 的函數式工具
受 Lodash 啟發、以泛型為優先的工具函式庫,提供 500+ 個型別安全的輔助函式,用於切片、映射、字串、數學、通道、元組和並發。零外部依賴。預設不可變。
官方資源:
此技能並非詳盡無遺。請參閱函式庫文件和程式碼範例以獲取更多資訊。Context7 可作為探索平台提供協助。如需 Go 套件文件、版本、符號和已知漏洞,→ 請參閱 samber/cc-skills-golang@golang-pkg-go-dev 技能。
為什麼選擇 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/lo |
lo |
1.18+ |
| 並發 | github.com/samber/lo/parallel |
lop |
1.18+ |
| 可變 | github.com/samber/lo/mutable |
lom |
1.18+ |
| 迭代器 | github.com/samber/lo/it |
loi |
1.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 扇出,請改用errgrouplom破壞不可變性 — 僅在測量到分配壓力時使用,切勿假設loi透過惰性求值消除鏈式操作(如Map → Filter → Take)中的中間分配- 對於反應式/串流管線處理無限事件串流,→ 請參閱
samber/cc-skills-golang@golang-samber-ro技能和samber/ro套件
如需詳細的套件比較和決策流程圖,請參閱 套件指南。
核心模式
轉換切片
// ✓ lo — 宣告式、型別安全
names := lo.Map(users, func(u User, _ int) string {
return u.Name
})
// ✗ 手動 — 樣板程式碼、容易出錯
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,
)
分組
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)
})
常見錯誤
| 錯誤 | 失敗原因 | 修正 |
|---|---|---|
使用 lo.Contains 而 slices.Contains 已存在 |
對標準函式庫已涵蓋的操作引入不必要的依賴 | 自 Go 1.21+ 起優先使用 slices.Contains/slices.Sort,自 Go 1.23+ 起需要鍵切片時使用 slices.Collect(maps.Keys(m)) |
對 10 個項目使用 lop.Map |
Goroutine 建立開銷超過轉換成本 | 使用 lo.Map — lop 的好處在 CPU 密集型工作中約從 1000+ 項目開始 |
假設 lo.Filter 會修改輸入 |
lo 預設不可變 — 它回傳一個新切片 |
如果明確需要原地變異,請使用 lom.Filter |
在生產程式碼路徑中使用 lo.Must |
Must 在錯誤時 panic — 在測試和初始化中沒問題,但在請求處理程式中很危險 |
使用非 Must 變體並處理錯誤 |
| 對大型資料鏈接多個急切轉換 | 每個步驟分配一個中間切片 | 使用 loi(惰性迭代器)避免中間分配 |
最佳實踐
- 優先使用標準函式庫(如果可用) —
slices.Contains和slices.Sort(Go 1.21+)無依賴;maps.Keys是 Go 1.23+ 並回傳迭代器,因此當你需要切片時使用slices.Collect(maps.Keys(m))。對於標準函式庫未提供的轉換(Map、Filter、Reduce、GroupBy、Chunk、Flatten),使用lo - 組合 lo 函式 — 鏈接
lo.Filter→lo.Map→lo.GroupBy,而不是撰寫巢狀迴圈。每個函式都是一個建構區塊 - 先分析再最佳化 — 僅在
go tool pprof確認分配或 CPU 是瓶頸後,才從lo切換到lom/lop - 使用錯誤變體 — 優先使用
lo.MapErr而非lo.Map加手動錯誤收集。錯誤變體提前停止並乾淨地傳播 - 僅在測試和初始化中使用
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 / 將 panic 轉為 bool |
lo.Async / lo.Attempt |
非同步執行 / 帶退避的重試 |
lo.Debounce / lo.Throttle |
速率限制 |
lo.ChannelDispatcher |
扇出到多個通道 |
如需完整的函式目錄(300+ 個函式),請參閱 API 參考。
如需組合模式、標準函式庫互通和迭代器管線,請參閱 進階模式。
如果你在 samber/lo 中遇到錯誤或意外行為,請在 github.com/samber/lo/issues 開啟問題。
交叉參考
- → 請參閱
samber/cc-skills-golang@golang-samber-ro技能,了解處理無限事件串流的反應式/串流管線(samber/ro套件) - → 請參閱
samber/cc-skills-golang@golang-samber-mo技能,了解可與 lo 轉換組合的單子型別(Option、Result、Either) - → 請參閱
samber/cc-skills-golang@golang-data-structures技能,了解如何選擇正確的底層資料結構 - → 請參閱
samber/cc-skills-golang@golang-performance技能,了解在切換到lom/lop前的效能分析方法





