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
510
パッケージ設計の黒魔術/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
920
GCPとGoの話/gcpug-osaka-6
lufia
0
510
調べながらGCPやってみた話/gcpug-osaka-3
lufia
1
510
REST is not only (web) API interface
lufia
1
1k
Go駆動開発で超速Pushエンジンを作った話
lufia
19
7.4k
Other Decks in Programming
See All in Programming
カスタマーサクセス業務を変革したヘルススコアの実現と学び
_hummer0724
0
490
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.4k
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
2.4k
CSC307 Lecture 01
javiergs
PRO
0
680
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30th Anniversary Party
k0kubun
1
390
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
110
AIフル活用時代だからこそ学んでおきたい働き方の心得
shinoyu
0
120
AIエージェントの設計で注意するべきポイント6選
har1101
7
3.4k
Data-Centric Kaggle
isax1015
2
750
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
180
CSC307 Lecture 07
javiergs
PRO
0
540
HTTPプロトコル正しく理解していますか? 〜かわいい猫と共に学ぼう。ฅ^•ω•^ฅ ニャ〜
hekuchan
2
670
Featured
See All Featured
Imperfection Machines: The Place of Print at Facebook
scottboms
269
14k
Context Engineering - Making Every Token Count
addyosmani
9
640
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
150
RailsConf 2023
tenderlove
30
1.3k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
0
2.3k
Technical Leadership for Architectural Decision Making
baasie
1
230
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.4k
Ethics towards AI in product and experience design
skipperchong
2
190
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
0
1.8k
Visualization
eitanlees
150
17k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
130
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