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
ASTで作るコンストラクタジェネレータ
Search
Takeru Furuse
August 08, 2024
Programming
0
12
ASTで作るコンストラクタジェネレータ
Takeru Furuse
August 08, 2024
Tweet
Share
Other Decks in Programming
See All in Programming
Duke on CRaC with Jakarta EE
ivargrimstad
0
310
ABEMA iOS 大規模プロジェクトにおける段階的な技術刷新 / ABEMA iOS Technology Upgrade
akkyie
1
260
GoとPHPのインターフェイスの違い
shimabox
2
220
Datadog DBMでなにができる? JDDUG Meetup#7
nealle
0
160
変化の激しい時代における、こだわりのないエンジニアの強さ
satoshi256kbyte
1
760
Devin入門 〜月500ドルから始まるAIチームメイトとの開発生活〜 / Introduction Devin 〜Development With AI Teammates〜
rkaga
3
1.1k
やっと腹落ち「スプリント毎に動くモノをリリースする」〜ゼロから始めるメガバンクグループのアジャイル実践〜
sasakendayo
0
230
PHPカンファレンス名古屋2025 タスク分解の試行錯誤〜レビュー負荷を下げるために〜
soichi
1
770
バッチを作らなきゃとなったときに考えること
irof
2
560
[JAWS DAYS 2025] 最近の DB の競合解決の仕組みが分かった気になってみた
maroon1st
0
190
Django NinjaによるAPI開発の効率化とリプレースの実践
kashewnuts
1
310
コードを読んで理解するko build
bells17
1
120
Featured
See All Featured
Done Done
chrislema
182
16k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7.1k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
580
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
Documentation Writing (for coders)
carmenintech
69
4.6k
Automating Front-end Workflow
addyosmani
1369
200k
Facilitating Awesome Meetings
lara
53
6.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
134
33k
Music & Morning Musume
bryan
46
6.4k
Agile that works and the tools we love
rasmusluckow
328
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.3k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
390
Transcript
ASTで作るコンストラクタジェネレータ 2024/08/08 golang.tokyo #36
About me 古瀬 たける / Takeru Furuse • 株式会社enechain (2023/12〜)
• エンジニア歴は約10年 • Go / Python / Typescriptをよく書きます • https://github.com/tsuperis3112 2024/8/8 1 Introduction
Todayʼs topic • コンストラクタジェネレータを作った話 • go/ast, go/types, golang.org/x/tools/go/packages等の使い分け • Genericsへの対応
• ASTでコード⽣成するときのハマりどころ 2024/8/8 2 Introduction
コンストラクタジェネレータとは What is a Constructor Generator? 3
モチベーション • ドメイン知識が複雑でエンティティのフィールドに変更が多数発 ⽣し構造体の初期化箇所でデグレが頻発 • Pythonのdataclass/pydantic(下図)やJavaのlombokのように⾃動で コンストラクタを⽣成してほしい 2024/8/8 4 コンストラクタジェネレータとは
概要 • 構造体に定義されたフィールド名、型を引数に取る関数 • embedされた構造体の各フィールドについても構造体名+フィール ド名のlower camel-caseを引数に取る • 構造体のポインタを返す •
同名の関数がパッケージ内に存在していれば、⽣成をスキップ 2024/8/8 5 コンストラクタジェネレータとは
出⼒イメージ 2024/8/8 6 コンストラクタジェネレータとは
設計・実装 Design and implementation 7
ファイル単位 パッケージ単位 AST関連のパッケージ群の役割 - 1 • golang.org/x/tools/go/packages • パッケージ情報を持つ •
*types.Scopeや[]*ast.Fileを参照 • go/types • 型情報 • *packages.Packageを参照 • go/ast • 構⽂の情報を持つ • 型の情報は含まない • go/token • リテラルや演算⼦などの構⽂中のトークン 2024/8/8 8 golang.org/x/tools/go/packages go/types go/ast go/token 設計・実装
AST関連のパッケージ群の役割 - 2 • golang.org/x/tools/go/packages • 何よりもまず*packages.Packageが起点になる • Embeddedされた構造体で利⽤されるフィールドの型など、不⾜しているimportを補う際に 利⽤
• Scopeを利⽤してgo/astとgo/typesの紐づけを⾏う • go/types • 構造体やフィールドの型情報を取得するために利⽤ • go/ast • Genericsの型引数に再帰的に値をアサインしていく 2024/8/8 9 設計・実装
型情報をトラ バース 型情報を⽊構 造のノードに 格納 ルートノード から型引数を マッピングし ていく リーフノード
から引数の情 報を⽣成する astutilで関数 を⽣成 全体の処理フロー 2024/8/8 設計・実装 10
構造体の定義 • StructMap • 必要な構造体の情報をキャッシュ • キーは「パッケージパス.構造体名」 • types.TypeName.Idと⼀致 •
依存関係を元に*ast.Fileにimportを追加する • Node • StructMapを元に出⼒される構造体 • この構造体を元にASTを構築してでコンストラクタを⽣成 2024/8/8 設計・実装 11
型情報のトラバース • *packages.Packageを起点にし て依存関係のあるパッケージ に含まれる構造体情報を取得 する 2024/8/8 12 設計・実装
Generics対応 • ここでも再帰的に型引数をアサ インしていく • ここでアサインした型引数を更 にネストされたGenerics構造体 にも適⽤する • 型パラメータ名を取得するため
にStructInfoにtypes.TypeSpecを 持たせている 2024/8/8 設計・実装 13
AST構築 • typeParamsはルートノードか ら取得 • Paramsはリーフノードから ⽣成 • compositeFieldsはルート ノードから再帰的に⽣成する
2024/8/8 設計・実装 14
振り返り Reflection 15
実装してみて • 複数のパッケージをまたぐことで型情報のパースが単純にはでき なかった • embedの循環参照が可能であったりと制約が⽐較的緩めなので、 ⾃前で制御する必要がある箇所が多かった • 再帰、再帰、再帰、再帰、、、 2024/8/8
振り返り 16
今後の展望 • OSS化 • フィールド値の⽣成関数対応 • UUIDなどを⾃動で⽣成してアサインさせる • バリデーション対応 •
現在は⽣成対象外フィールドだけタグで指定できるようにしている • go-playground/validatorなどをラップする形? • プラグイン対応 • 初期化時になにかの処理をHookさせられるようにしたい 2024/8/8 振り返り 17
ご清聴ありがとうございました Thank you for your attention 18