Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GoのDB アクセスにおける 「型安全」と「柔軟性」の両立 - Bob という選択肢

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for tak tak
March 13, 2026

GoのDB アクセスにおける 「型安全」と「柔軟性」の両立 - Bob という選択肢

https://layerx.connpass.com/event/383847/

サンプルにbobをふんだんに使ったアプリとdocsを作ってもらったのでぜひこちらも!
https://github.com/tak848/lxgo4-bob

Avatar for tak

tak

March 13, 2026
Tweet

More Decks by tak

Other Decks in Programming

Transcript

  1. @tak848_ © LayerX Inc. Self Introduction 高橋拓也(tak) LayerX バクラク事業部 (2023-12

    -) エンジニア / 25新卒 週末に確定申告しなければ...
  2. 皆さん、Go で DB アクセスどうしてますか 系統 代表例 強いところ つらいところ ORM GORM

    柔軟。導入事例も多い 型が弱め。ゼロ値事故がある SQL First sqlc 型安全。レビューしやすい 動的クエリがしんどい 薄いラッパ sqlx 生 SQL を素直に書ける 型安全や生成支援は薄い DB schema 生成 xo / SQLBoiler / bob DB を正としてコード生成できる ツール選定の差が大きい Code First ent スキーマ定義から一貫管理しやすい 既存 DB 起点では乗せにくい 今日はこの中でも DB schema 生成系 をベースに、bob を見ます © LayerX Inc. 3
  3. bob にたどり着く入口が SQLBoiler © LayerX Inc. Go の Schema First

    系 でかなり有名だったコード生成ツール DB スキーマから Model や CRUD を生成する その SQLBoiler が maintenance mode に入った 4
  4. GORM 良い つらい 典型例 柔軟ではある。でも「意図した値が飛ぶか」を型が 守ってくれない。 © LayerX Inc. 比較

    エコシステム成熟。GitHub Stars 39k 社内全サービスで実績 動的クエリの組み立てはやりやすい interface{} 多用で型チェックが効きにくい ゼロ値トラップで false / 0 / "" が落ちる AI がコードを書く時代にこれはかなりつらい 9
  5. sqlc 良い つらい 典型例 静的 SQL は強い。でも管理画面系のフィルタが増 えると、この書き味はしんどい。 © LayerX

    Inc. 比較 SQL first で型安全 生成 SQL が 100% 予測可能 レビューしやすい 動的クエリがかなり苦しい boolean フラグパターンに寄りがち バルクインサートも歴史的に弱かった 10
  6. xo / SQLBoiler 良い つらい 典型例 自由度は高い。でも「生成してからさらに整える」 工程は、地味に重い。 © LayerX

    Inc. 比較 DB スキーマ駆動でモデル生成 自由度は高い LayerX では xo + 自前ツールでかなり育っている SQLBoiler はメンテナンスモード xo はクエリビルダーがない 生成後の後処理が増えると運用コストが乗る 11
  7. bob 良い 課題 書き味 自分が欲しかった「GORM の柔軟さ」と「sqlc の型 安全さ」に一番近い。 © LayerX

    Inc. 比較 型安全 × 柔軟 × database/sql ネイティブ queries plugin で sqlc 的なこともできる Model / Setter 分離や 3 状態型まで入っている Stars 1.6k でまだ小さい ドキュメントは多くない 名前で検索しづらい 12
  8. まず bob の generator は何をしているか 入力 DB スキーマ bobgen.yaml queries/*.sql

    → 生成 Model Setter enum Where / Relation / Factory → 使う場所 CRUD 動的クエリ 集計 SQL テストデータ作成 DB が Single Source of Truth。マイグレーション後に bobgen するだけ。 © LayerX Inc. bob の具体コード 14
  9. bob generate — 設定は bobgen.yaml ここで決めること © LayerX Inc. bob

    の具体コード どの plugin を使うか 生成先ディレクトリ DB 方言と接続先 queries を読むか 15
  10. 生成される Task モデル © LayerX Inc. bob の具体コード NOT NULL

    → Go 型そのまま、NULLABLE → null.Val[T] PostgreSQL ENUM → 生成された enum 型( enums.TaskStatus 等) 16
  11. TaskSetter — Model と Setter が分離している HTTP でいう PUT /

    PATCH の違いが型で表現できる。 未セットのフィールドは SQL に含まれない → PATCH 的な部分更新が自然にできる © LayerX Inc. bob の具体コード 17
  12. omit / omitnull — 3 状態型 操作 コード SQL への影響

    値をセット omit.From("hello") SET title = 'hello' NULL をセット v.Null() SET assignee_id = NULL 未セット ゼロ値のまま SQL に含まれない GORM のゼロ値問題が 「型レベルで」消える。 0 , "" , false を安全に扱える © LayerX Inc. bob の具体コード 18
  13. INSERT — RETURNING * で結果が返る MySQL の再取得まわりの修正例: PR #638 ©

    LayerX Inc. bob の具体コード Setter で指定した列だけ INSERT created_at / updated_at は DB 側で入る PostgreSQL は RETURNING でそ のまま返せる MySQL は INSERT 後に再取得す る 20
  14. リレーション — Preload / ThenLoad to-one は JOIN、to-many は別クエリで N+1

    回避。GORM の Preload 巨大 IN 句問題も起きない © LayerX Inc. bob の具体コード 23
  15. 他にもうれしいこと xo + 自前後処理でやっていたことが、bob だとかなり減る © LayerX Inc. bob の具体コード

    replacements で型オーバーライド PostgreSQL ENUM → Go enum 自動生成 テスト用 Factory 自動生成 dberrors で unique 制約違反の判定ヘルパー生成 25
  16. database/sql ネイティブ 「試してダメなら戻せる」が担保される 導入の心理的ハードルが低い。これは大きい © LayerX Inc. bob の具体コード 既存の

    *sql.DB / *sql.Tx を薄く wrap して持ち込める database/sql ベースの既存資産と距離が近い Datadog APM、コネクションプーリング、IAM 認証ともつなぎやすい 26
  17. LayerX で GORM Hook に載せていた発想を bob でもやる やっていること 狙い LayerX

    では GORM Hook で tenant_id を差し込んでいた。その 発想を sample app では workspace_id で再現している。 © LayerX Inc. 導入中の工夫 Service 層に WHERE workspace_id を書かない SELECT / UPDATE / DELETE に横断で差し込める 28
  18. ここは template / generator に寄せるとよい sample app 実案件ではここを自動化したい ORM 本体を置き換えるというより、自分たちが欲しい薄い自動化を足せる

    のが bob のおもしろさ © LayerX Inc. 導入中の工夫 members / projects / tasks / task_comments に手で登録 動きは分かりやすい でもテーブルが増える とだるい 29
  19. 評価済み / まだ検証中 かなり良い手応え まだ検証中・悩み中 © LayerX Inc. まとめ Model

    / Setter 分離 omit / omitnull の 3 状態型 QueryMod で型安全な動的クエリ queries plugin で SQL 直書きとの両立 database/sql ネイティブ 大規模テーブルでのパフォーマンス template / generator をどこまで持つか RLS は DB ガードとして薄く検証中 生成モデルをどこまでロジック層に使うか 重要なのは 安全に価値を最速で届けること 30
  20. まとめ 発表で触れたコードはサンプルリポジトリでも追えるようにします © LayerX Inc. まとめ Go の DB アクセスでは、型安全か柔軟性のどちらかを諦めがちだった

    bob は Model/Setter 分離、3 状態型、QueryMod、SQL 直書きとの両立で 両方を追求 する設計 database/sql ネイティブなので段階的導入・撤退が可能 xo + fieldtypereplacer でやっていたことが bob だけで完結する 今まさに導入中。かなり有力な選択肢だと感じている 31
  21. Sample Repository リポジトリで見られるもの 公開先 lxgo4-bob https://github.com/tak848/lxgo 4-bob スライドで全体像、repo で実コードと docs

    を追えるようにします © LayerX Inc. Sample Repository タスク管理デモアプリ(API + webapp) Model / Setter / omit 系の挙動 QueryHooks / relations / queries plugin の実 例 docs/ に bob の使い方を章立てで整理 32