Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GoのGenericsによるslice操作との付き合い方
Search
syumai
June 18, 2025
Programming
1.1k
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
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.5k
Oxlintのカスタムルールの現況
syumai
6
1k
Oxlintはいかにしてtsgolintのlint ruleを呼び出しているのか
syumai
2
1.1k
『[入門] Cloudflare Workers』本はなぜ誕生したのか
syumai
0
360
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
9
3.1k
知られているようで知られていない JavaScriptの仕様 4選
syumai
3
1.2k
CloudflareのSandbox SDKを試してみた
syumai
0
840
実践AIチャットボットUI実装入門
syumai
9
4.2k
ProxyによるWindow間RPC機構の構築
syumai
3
1.5k
Other Decks in Programming
See All in Programming
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
440
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
120
3Dシーンの圧縮
fadis
1
660
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
110
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
620
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
250
CSC307 Lecture 17
javiergs
PRO
0
310
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
380
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
220
今さら聞けないCancellationToken
htkym
0
220
Spec-Driven Development with AI-Agents: From High-Level Requirements to Working Software
antonarhipov
2
460
The Arts and Crafts of Work in the AI Era — Toward Mastery in Software Development
kuranuki
1
730
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
830
A designer walks into a library…
pauljervisheath
211
24k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
820
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
380
Into the Great Unknown - MozCon
thekraken
41
2.5k
Tell your own story through comics
letsgokoyo
1
950
Faster Mobile Websites
deanohume
310
31k
Visualization
eitanlees
152
17k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
380
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 操作は残念ながらまだ現役
ご清聴ありがとうございました!