Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GoのGenericsによるslice操作との付き合い方
Search
syumai
June 18, 2025
Programming
1.2k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GoのGenericsによるslice操作との付き合い方
golang.tokyo #39 の発表資料です
https://golangtokyo.connpass.com/event/353988/
syumai
June 18, 2025
More Decks by syumai
See All by syumai
Workers Cache を知る
syumai
0
390
自分的「カンファレンスの楽しみ方」
syumai
0
220
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.6k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
2.2k
Oxlintのカスタムルールの現況
syumai
6
2.2k
Oxlintはいかにしてtsgolintのlint ruleを呼び出しているのか
syumai
2
1.7k
『[入門] Cloudflare Workers』本はなぜ誕生したのか
syumai
0
660
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
9
3.4k
知られているようで知られていない JavaScriptの仕様 4選
syumai
3
1.3k
Other Decks in Programming
See All in Programming
Railsバージョンを4倍にした話
optim
0
800
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
360
Groovy as a human and AI friendly programming language
paulk
0
120
Performance Optimization With LLMs
xleitix
0
210
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
260
R8 の設定見直しでアプリサイズ削減
andpad
0
230
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
5
1.1k
プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析
ostk0069
0
130
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
1.2k
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
190
AI-Powered Domain-Driven Design
ziobrando
0
340
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
480
Featured
See All Featured
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
270
We Are The Robots
honzajavorek
0
410
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
470
Music & Morning Musume
bryan
48
7.5k
Unsuck your backbone
ammeep
672
58k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
530
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Typedesign – Prime Four
hannesfritz
42
3.2k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
330
Transcript
Go のGenerics によるslice 操作との付き合い方 syumai golang.tokyo #39 (2025/6/18)
自己紹介 syumai ECMAScript 仕様輪読会 / Asakusa.go 主催 株式会社ベースマキナで管理画面のSaaS を開発中 Go
でGraphQL サーバー (gqlgen) や TypeScript でフロント エンドを書いています Software Design 2023 年12 月号から2025 年2 月号まで Cloudflare Workers の連載をしました Twitter ( 現𝕏): @__syumai Website: https://syum.ai
今日話すこと basemachina/lo の紹介 実装のモチベーション i. 従来のslice 操作の課題 ii. samber/lo 導入の課題
slice 変換機能の使い方 ( おまけ) イテレータの利用状況
basemachina/lo
basemachina/lo Generics を使って Map , Filter などの操作をslice に対して簡単に行えるライブラリ 型情報を使ったslice 以外の操作も必要に応じて追加している
numbers := []int{1, 2, 3, 4, 5} doubled := lo.Map(numbers, func(x int) int { return x * 2 }) fmt.Println(doubled) // [2, 4, 6, 8, 10] evens := lo.Filter(numbers, func(x int) bool { return x%2 == 0 }) fmt.Println(evens) // [2, 4] fmt.Printf("%T\n", lo.ToPtr(1)) // *int
現在使える機能 ( 全19 種類) * Array/Slice操作 - フィルタリング - Filter
- FilterWithIndex - 変換 - Map - MapWithError - MapWithIndex - MapWithIndexError - FlatMap - FlatMapWithIndex - 検索・判定 - Find - Every - Some - HasDuplicates - HasDuplicatesBy - 集約 - Reduce - ReduceWithIndex - 集合演算 - Intersect * Map操作 - Invert * ポインタ操作 - ToPtr - FromPtrOr
実装のモチベーション
1. 従来のslice 操作の課題
None
None
None
1. 従来のslice 操作の課題 range を使った詰め替えでは、うっかり事故る可能性がある lint を入れて防ぐしかない ( 私見) lo.Map
や lo.Filter などの関数を使ったコードの方が読むのが楽 行いたい操作が関数名から明確 slice 操作の実装の詳細を確認しなくていい
2. samber/lo 導入の課題
2. samber/lo 導入の課題 機能が充実しすぎている 全部を使いたい訳ではない 学習コストを問題視
https://pkg.go.dev/github.com/samber/lo
はてなさんの事例 https://github.com/hatena/godash 今はiter 推奨らしい
basemachina/lo のslice 変換機能の使い方
basemachina/lo のslice 変換機能の使い方 DB から取ってきたデータを変換してGraphQL resolver から返す処理 func (r *queryResolver)
Views(ctx context.Context) ([]*gql.View, error) { // []*model.View を取得 views, err := loader.ListViews(ctx, r.project.ID) if err != nil { return nil, err } // []*gql.View を返却 return lo.Map(views, gqlpresenter.View), nil }
basemachina/lo のslice 変換機能の使い方 basemachina/lo 無しの場合 func (r *queryResolver) Views(ctx context.Context)
([]*gql.View, error) { // []*model.View を取得 views, err := loader.ListViews(ctx, r.project.ID) if err != nil { return nil, err } // []*gql.View を返却 gqlViews := make([]*gql.View, len(views)) for i, v := range views { gqlViews[i] = gqlpresenter.View(v) } return gqlViews }
basemachina/lo のslice 変換機能の使い方 変換用のコードは使い回せるので別package で実装 lo.Map のシグニチャを変えて (item T, index
int) を (item T) だけにして いるのでこれでOK package gqlpresenter func View(v *model.View) *gql.View { return &gql.View{ ID: v.ID, Name: v.Name, Code: v.Code, } }
もし lo.Map のシグニチャが iteratee (item T, index int) だったら 変換処理側で合わせる場合
package gqlpresenter // 毎回 `_ int` を書かないといけない func View(v *model.View, _ int) *gql.View { return &gql.View{ ID: v.ID, Name: v.Name, Code: v.Code, } }
もし lo.Map のシグニチャが iteratee (item T, index int) だったら 変換処理を使う側で合わせる場合
func (r *queryResolver) Views(ctx context.Context) ([]*gql.View, error) { views, err := loader.ListViews(ctx, r.project.ID) if err != nil { return nil, err } // 毎回無名関数を書く return lo.Map(views, func (v *model.View, _ int) *gql.View { return gqlpresenter.View(v) }), nil }
basemachina/lo のslice 変換機能の使い方 変換時にエラーが発生しうる場合は lo.MapWithError を使う func (r *queryResolver) Actions(ctx
context.Context) ([]*gql.Action, error) { /* ... */ return lo.MapWithError(actions, gqlpresenter.Action) }
basemachina/lo のslice 変換機能の使い方 MapWithIndexError (MapWithError の内部で呼ぶ) の実装 https://github.com/samber/lo/pull/43 で提案 func
MapWithIndexError[T any, R any]( collection []T, iteratee func(item T, index int) (R, error)) ([]R, error) { result := make([]R, len(collection)) var err error for i, item := range collection { result[i], err = iteratee(item, i) if err != nil { return nil, err } } return result, nil }
( おまけ) イテレータの利用状況
イテレータ、積極的に使っていますか?
社内のイテレータの利用状況 社内では導入がほぼ進んでいない ほとんどがslice の変換だけで済んでしまうユースケースのみ
Go のxiter package proposal がClose データ列の変換目的でのイテレータ導入の理由は弱くなった https://github.com/golang/go/issues/61898
パフォーマンスチューニング目的での導入はありうる https://developers.cyberagent.co.jp/blog/archives/54653/
補足 - xiter 以外の選択肢 go-functional https://github.com/BooleanCat/go-functional Go のイテレータを使って関数型チックにコードを書けるライブラリ ヘルパー関数も充実している
まとめ
まとめ Generics を活用したslice 操作ライブラリの自前実装を持つのは便利 slice 操作のスタイルを統一できる イテレータを使わないslice 操作は残念ながらまだ現役
ご清聴ありがとうございました!