golang-samber-lo について
samber/lo を扱う Go スキルです。ジェネリクスベースのユーティリティによる宣言的なコレクション変換を説明し、標準ライブラリを優先する場面や関連パッケージの選び方も示します。
主な機能
- 01スライスとマップ向けのジェネリック関数
- 02データの変換、絞り込み、集約、グループ化
- 03エラーを返す関数バリアント
- 04並列・可変・イテレータの各パッケージ
- 05標準ライブラリの選択とプロファイリング指針
活用シーン
- 01定型的なコレクションループの置き換え
- 02データ変換パイプラインの構成
- 03計測後に遅延処理や並列処理を選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ samber/ cc-skills-golang --skill golang-samber-loインストール後、Claude Code で/golang-samber-loを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/advanced-patterns.mdapi-reference.mdpackage-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)を参照してください。 - Context7 は、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 バージョン |
|---|---|---|---|
| Core(不変) | 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(実験的) | github.com/samber/lo/exp/simd | — | 1.25+(amd64 のみ) |
適切なパッケージを選ぶ
まずは lo を使ってください。他のパッケージへの切り替えは、プロファイリングでボトルネックが確認された場合や、遅延評価が明示的に必要な場合に限ります。
| パッケージ | 使用する場面 | トレードオフ |
|---|---|---|
lo | すべての変換におけるデフォルト | 新しいコレクションを割り当てます(安全で予測可能) |
lop | 大規模なデータセット(1000+ 項目)に対する CPU バウンド処理 | ゴルーチンのオーバーヘッドがあります。I/O や小さなスライスには不向きです |
lom | pprof -alloc_objects でホットパスが確認された場合 | 入力を変更するため、呼び出し側は副作用を把握する必要があります |
loi | 連結した変換を適用する大規模なデータセット(Go 1.23+) | 遅延評価でメモリを節約できますが、イテレーターの複雑さが増します |
simd | ベンチマーク後の数値一括処理(実験的) | API は不安定で、バージョン間で変更される可能性があります |
重要なルール:
lopは CPU の並列処理向けであり、I/O の並行処理向けではありません。I/O のファンアウトには、代わりにerrgroupを使用してくださいlomは不変性を損ないます。割り当てによる負荷が測定された場合に限って使用し、推測で使わないでくださいloiは遅延評価によって、Map → Filter → Takeのようなチェーン内の中間割り当てをなくします- 無限のイベントストリームに対するリアクティブ/ストリーミングのパイプラインについては、→
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)
}
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": [...]}
エラー対応のバリエーション — 最初のエラーで停止
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 を使う | ゴルーチンの生成コストが変換コストを上回ります | lo.Map を使います。lop の効果が得られるのは、CPU バウンドの処理でおよそ 1000 個以上の要素がある場合です |
lo.Filter が入力を変更すると想定する | lo はデフォルトでイミュータブルであり、新しいスライスを返します | インプレースでの変更が明示的に必要な場合は lom.Filter を使います |
本番コードの処理経路で lo.Must を使う | エラーが発生すると Must はパニックを起こします。テストや初期化では問題ありませんが、リクエストハンドラーでは危険です | 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.Mapと手動でのエラー収集を組み合わせるのではなく、lo.MapErrを優先します。エラー処理用のバリアントは早期に処理を停止し、エラーを適切に伝播します lo.Mustはテストと初期化でのみ使います — 本番コードでは、エラーを明示的に処理します
クイックリファレンス
| 関数 | 動作 |
|---|---|
lo.Map | 各要素を変換します |
lo.Filter / lo.Reject | 条件を満たす要素を残す/除外します |
lo.Reduce | 要素を単一の値に畳み込みます |
lo.ForEach | 副作用を伴う反復処理を行います |
lo.GroupBy | キーに基づいて要素をグループ化します |
lo.Chunk | 固定サイズのバッチに分割します |
lo.Flatten | ネストしたスライスを 1 階層平坦化します |
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 | 2 つのスライスをペアにする/ペアを解除します |
lo.Range / lo.RangeFrom | 数値のシーケンスを生成します |
lo.Ternary / lo.If | インライン条件分岐を行います |
lo.ToPtr / lo.FromPtr | ポインター関連のヘルパーです |
lo.Must / lo.Try | エラー時にパニックを起こす/エラーをブール値として復元します |
lo.Async / lo.Attempt | 非同期実行/バックオフを伴う再試行を行います |
lo.Debounce / lo.Throttle | レート制限を行います |
lo.ChannelDispatcher | 複数のチャネルにファンアウトします |
関数の完全なカタログ(300 以上の関数)は、API リファレンスを参照してください。
関数の組み合わせパターン、標準ライブラリとの連携、イテレーターパイプラインについては、高度なパターンを参照してください。
samber/lo でバグや予期しない動作が発生した場合は、github.com/samber/lo/issues で issue を作成してください。
関連項目
- → 無限イベントストリーム上のリアクティブ/ストリーミングパイプライン(
samber/roパッケージ)については、samber/cc-skills-golang@golang-samber-roスキルを参照してください - → lo の変換と組み合わせられるモナド型(Option、Result、Either)については、
samber/cc-skills-golang@golang-samber-moスキルを参照してください - → 適切な基盤データ構造の選択については、
samber/cc-skills-golang@golang-data-structuresスキルを参照してください - →
lom/lopに切り替える前のプロファイリング手法については、samber/cc-skills-golang@golang-performanceスキルを参照してください