Slide 1

Slide 1 text

Goでリフレクションする、その 前に Kansai.go #1 @utgwkk (うたがわきき)

Slide 2

Slide 2 text

自己紹介 @utgwkk (うたがわきき) 株式会社はてな Webアプリケーションエンジニア in 京都 好きなパッケージはreflect

Slide 3

Slide 3 text

ここで宣伝 Go Conference 2024 (6/8) で登壇します Dive into gomockというタイトルでやります 渋谷で会いましょう

Slide 4

Slide 4 text

リフレクション 実行時にプログラムの情報を読み書きすること Goでは、主にreflectパッケージを使うことで実現できる 例: 実行時に型情報を取得する、struct tagの情報を取得する、など

Slide 5

Slide 5 text

こんなとこにもリフレクション (1) encoding/json パッケージによるJSONシリアライズ・デシリアライズ type S struct { X int `json:"x"` Y string `json:"y" Z int `json:"z,omitempty"` } b, _ := json.Marshal(S{X: 100, Y: "hello"}) fmt.Println(string(b)) // {"x":100,"y":"hello"}

Slide 6

Slide 6 text

こんなとこにもリフレクション (2) github.com/jmoiron/sqlx を使ったDBアクセス type User struct { Id int `db:"id"` Name string `db:"name"` } user := User{} _ = db.GetContext( ctx, &user, `SELECT * FROM user WHERE id = ?`, id, )

Slide 7

Slide 7 text

こんなとこにもリフレクション (3) github.com/caarlos0/env を使った環境変数のパース type Config struct { Addr string `env:"ADDR"` IsLocal bool `env:"IS_LOCAL" envDefault:"false"` } cfg := Config{} _ = env.Parse(&cfg)

Slide 8

Slide 8 text

リフレクションを使いたくなったらまず立ち止まる 生きていると一度はリフレクションを使いたくなる (こともある) ここでいったん深呼吸しましょう それ、リフレクションじゃなくてもできるのでは??

Slide 9

Slide 9 text

素直に実装する まずは素直に書いてみましょう…… 型やinterfaceをうまく活用すると実現できるかもしれない 分岐の数が限られているなら素直に書いたほうが早い

Slide 10

Slide 10 text

ジェネリクス Go 1.18からジェネリクスが導入された スライスやmapに対する操作を書きやすくなっている any型の登場頻度が減っている

Slide 11

Slide 11 text

コード生成 対象となるデータ型が限られているなら非常に有効 リフレクションよりも高速であることが期待しやすい コード生成特有のテクニックは求められるかも

Slide 12

Slide 12 text

それでもリフレクションを使うなら ようこそリフレクションへ

Slide 13

Slide 13 text

リフレクションは黒魔術 実質的にany型しかない (動的型だと思って書く) ランタイムの気持ちになりながらコードを書く 前提条件チェックに失敗するとすぐpanicする

Slide 14

Slide 14 text

リフレクションが有効な場面 対象となるデータ型の範囲を絞れない (ライブラリとか) 型やinterfaceを活用するだけでは実現できない 実行時の型情報にアクセスしたい struct tagを活用したい 実行速度やメモリ効率をさほど気にしなくてもよい

Slide 15

Slide 15 text

リフレクションを使うプログラミングのコツ デバッガを差し込む (あるいはprintデバッグする) ランタイムの気持ちになる ポインタと値が厳密に区別されることを頭に叩き込む reflectパッケージのドキュメントや実装を読む リフレクションを使ったライブラリの実装を参考にする

Slide 16

Slide 16 text

リフレクションを使ったライブラリの実装を参考にする よく使われている・テストされているライブラリは考慮が行き届いているだろう このあたりが読みやすい (発表者の意見です) github.com/caarlos0/env github.com/jmoiron/sqlx

Slide 17

Slide 17 text

まとめ リフレクションを使わずに解決できないか、最初に検討しよう 用法用量を守って正しくリフレクションと付き合おう リフレクションで手札が広がるのと同時に、自分の身を自分で守ることになる

Slide 18

Slide 18 text

最後に宣伝 Goのリフレクションと向き合う同人誌を書きました (去年の冬に) booth.pm で購入できます https://utgwkk.booth.pm/items/5376961