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
パッケージ設計の黒魔術/Kyoto.go#63
Search
kadota kyohei
August 31, 2025
Programming
3
470
パッケージ設計の黒魔術/Kyoto.go#63
黒魔術の話です
kadota kyohei
August 31, 2025
Tweet
Share
More Decks by kadota kyohei
See All by kadota kyohei
最近変わった開発時のあれこれ/features-of-recent-go
lufia
0
900
GCPとGoの話/gcpug-osaka-6
lufia
0
500
調べながらGCPやってみた話/gcpug-osaka-3
lufia
1
500
REST is not only (web) API interface
lufia
1
990
Go駆動開発で超速Pushエンジンを作った話
lufia
19
7.4k
Other Decks in Programming
See All in Programming
TFLintカスタムプラグインで始める Terraformコード品質管理
bells17
2
360
Cursorハンズオン実践!
eltociear
2
1.2k
テーブル定義書の構造化抽出して、生成AIでDWH分析を試してみた / devio2025tokyo
kasacchiful
0
280
Introduce Hono CLI
yusukebe
6
3.1k
CSC305 Lecture 10
javiergs
PRO
0
230
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
260
Go言語の特性を活かした公式MCP SDKの設計
hond0413
1
490
AI 駆動開発におけるコミュニティと AWS CDK の価値
konokenj
5
220
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
330
AIと人間の共創開発!OSSで試行錯誤した開発スタイル
mae616
2
800
コード生成なしでモック処理を実現!ovechkin-dm/mockioで学ぶメタプログラミング
qualiarts
0
260
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
3
710
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.7k
How GitHub (no longer) Works
holman
315
140k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
The Language of Interfaces
destraynor
162
25k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Fireside Chat
paigeccino
41
3.7k
Gamification - CAS2011
davidbonilla
81
5.5k
Stop Working from a Prison Cell
hatefulcrawdad
272
21k
YesSQL, Process and Tooling at Scale
rocio
173
15k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Six Lessons from altMBA
skipperchong
29
4k
Transcript
パッケージ設計の黒魔術 id:lufiabb / @plan9user 2025/08/31 Kyoto.go #63 オフラインLT会 1
今日の話 • reflect.StructField.Offset • go build -overlay=[file] • ovechkin-dm/go-dyno 2
3 StructField.Offset
Offset • reflectで構造体フィールドを探すとき • 名前やインデックスはよくある ◦ reflect.Value.FieldByIndex ◦ reflect.Value.FieldByName •
メモリ上のオフセットでも特定できる ◦ reflect.StructFieldにOffsetフィールドがある 4
Offset type User struct { ID int Active bool Name
string } 5 ID Offset 0 未使用(アラインメント) Active Name Offset 8 Offset 16
使い方 p0 := reflect.ValueOf(&u).Pointer() p1 := reflect.ValueOf(&u.Active).Pointer() off := p1
- p0 for _, f := range reflect.VisibleFields(reflect.TypeOf(u)) { if f.Offset == off { fmt.Println(f.Name) // Output: Active } } 6
何が嬉しいの 型パラメータと一緒に使うと型を残せる func Assert[T, F any](u T, p *F) Equaler[F]
Assert(u, &u.Name).Equal(“example”) 7 型を間違えると ビルドエラー
よくあるやつ type User struct { ID int `json:”id” validate:”qte=1”` Name
string `json:”name” validate:”required”` } 文字列で指示するものは同じ問題が起きがち 8 長くなりがち typoしても気づかない
バリデーションにも活かせる validation.ValidateStruct( validation.Field(&s.ID, validation.Min(1)), validation.Field(&s.Name, validation.Required()), ) 9 改行できる 型情報が活かせる
10 -overlay=[file]
overlayオプション • go build -overlay=[file] ◦ tenntenn/testtimeで知った • 特定のファイルをビルド時に置き換える 11
overlay.json { “Replace”: { “変更したいファイルパス ”: “変更後のファイルパス ” } }
go build -overlay=overlay.json 12
何が起きるのか • ビルド時に動的なファイル置換が起きる • osやruntimeのファイルも変えられる • 実質的になんでもできる ◦ 当然Goのバージョンが上がったら壊れる(こともある) 13
実用例 scope := plug.CurrentScope() defer scope.Delete() key := plug.Func("os.Getpid", os.Getpid)
plug.Set(scope, key, func() int { return 1 }) 14
実用例 key := plug.Func("os.Getpid", os.Getpid) ソースコードが分かれば一部の関数だけ変更するのは簡単 静的解析で overlayファイルを自動生成できる ※ とても行儀は悪いのでテスト用途に留めましょう
15 静的解析でパッケージの ソースコードが取れる Funcをマーカーとし て静的解析で探す
16 go-dyno
go-dyno • ovechkin-dm/go-dyno • 動的にインターフェイスを実装するライブラリ ◦ 普通の方法ではできない 17
go-dyno • ovechkin-dm/go-dyno • 動的にインターフェイスを実装するライブラリ ◦ 普通の方法ではできない 18
普通の方法 • 構造体フィールドを動的に生成できる • 関数もある程度は動的に生成できる • メソッドは作れない ◦ runtimeやunsafeにもそんなものはない 19
go-dynoの使用例 iface, err := dyno.Dynamic[io.Reader](handleMethod) func handleMethod( method reflect.Method, args
[]reflect.Value, ) []reflect.Value { return nil } 20 メソッド名が取れる 引数も取れる 実装したいインターフェイス
go-dyno • インターフェイスをモックしたければコード生 成しかない(と思っていた) ◦ コード生成は遅いしコンフリクトも多い • go-dynoで選択肢が広がった • GoCon
2025でkaramaruさんが話すらしい 21
まとめ • ライブラリデザインに使えそうな黒魔術を3つ 紹介しました • デザインの参考になれば嬉しいです 22