🌈

GoのORM全然ワカンナイからチョットワカルにする

2024/12/04に公開

はじめに

個人開発やってみたい〜、最近流行ってるGoってやつでやってみようかな〜、けどORMってなんだこれいっぱいあるぞ(一年前の自分)
そういう状態の人におすすめの記事になっています!
Waffleアドベントカレンダー6日目の記事です。

ORMとは

Object-Relational Mapping(ORM)は、プログラミング言語のオブジェクトとデータベースのテーブルを相互変換するための技術です。ORMを使用することで、開発者は生のSQLを直接記述する代わりに、オブジェクト指向的な方法でデータベース操作を行えます。

ORMの主な利点は以下の通りです:

  • データベーススキーマとコードの構造を自動的にマッピング
  • クロスデータベース対応
  • セキュリティの向上(SQLインジェクション対策)
  • 開発生産性の向上

ORM自体の説明に関してはこちらの記事がわかりやすかったです!

ORMを使わないという選択肢

Goには組み込みのORMが存在せず、標準ライブラリのdatabase/sqlパッケージで十分な機能が提供されています。

以下のような場合にはORMを使わない選択肢もありです:

  • 小規模なプロジェクト: 必要最低限の機能だけで十分な場合
  • SQLの学習目的: SQLに精通したい場合
  • パフォーマンス重視: 不要な抽象化を排除したい場合
    初心者で「まずはGoを使ったプロダクト開発を体験してみたい」という場合には、標準ライブラリでの実装もおすすめです。

型安全性とは

ORMを紹介する前に、ORMの選定でキーワードになってくる型安全性について説明します。
型安全性とは、プログラミング言語やツールが、データの型に関するエラーを事前に検出し、防ぐ仕組みのことです。簡単に言えば、「間違った型のデータを使おうとしたときに、できるだけ早い段階でエラーを知らせてくれる仕組み」です。

型安全性の具体例

型安全でない例(リスク)

go
Copy
// 型安全でない場合
func processUser(data interface{}) {
// どんな型の値でも受け取れてしまう
    user := data.(User)// 実行時にパニックする可能性がある
}

// 間違った型の値を渡せてしまう
processUser("文字列")// 実行時にエラー!

型安全な例

go
Copy
// 型安全な実装
func processUser(user User) {
// User型であることが保証されている
    fmt.Println(user.Name)
}

// コンパイル時にエラーを検出
processUser("文字列")// コンパイルエラー!

型安全性の利点

  1. 早期エラー検出
    • コンパイル時にエラーを発見
    • 実行時のエラーを未然に防ぐ
  2. コードの信頼性向上
    • 型の不整合を自動的にチェック
    • 意図しない型変換を防ぐ

ORM紹介

それではそれぞれのORMについて説明していきます!浅学なので間違ってるとこがあれば教えてください!

🌈 GORM - 最も親しみやすいORM

  • 「初心者でも簡単に使えるORM」と言われるライブラリ
  • Goで最も人気のあるデータベースライブラリ
  • SQLの知識がなくても、直感的にデータベース操作ができる

メリット

  1. 超シンプルな操作

    // ユーザー作成がこれだけ!
    db.Create(&user)
    
    // 検索もワンライナー
    db.Where("name = ?", "John").First(&user)
    
    
  2. 自動マイグレーション

    • データベーススキーマを自動で作成・更新
    • モデル定義だけで、テーブル構造が決まる
    db.AutoMigrate(&User{})
    
    
  3. 豊富な機能

    • リレーション(関連)の自動管理
    • トランザクション処理
    • プラグイン拡張

デメリット

  • パフォーマンスがやや遅い
  • 複雑なクエリは少し書きづらい
  • メモリ使用量が多い

🔒 SQLBoiler - 型安全性重視

  • コード生成型のORM
  • データベーススキーマから自動的にGoのコードを生成(嬉しい)
  • 「型安全性」に最大の特徴

メリット

  1. コンパイル時の型チェック

    // 自動生成されたコード
    user, err := models.Users().One(ctx, db)
    
  2. 高速な実行性能

    • 生成されるコードは非常に最適化されている
    • リフレクションを最小限に抑えている
  3. スキーマ変更の追従が容易

    • データベーススキーマが変わると、自動的にコードを再生成

デメリット

  • 初期設定が少し複雑
  • スキーマ変更のたびにコード再生成が必要
  • 学習コストがやや高い

🚀 SQLc - SQLの力を最大限に活用

  • SQLを直接書きながら、型安全なコードを生成
  • 「SQLの柔軟性」と「型安全性」を両立

メリット

  1. 生のSQLを書ける

    // SQL文を直接定義
    const createUser = `
      INSERT INTO users (name, email)
      VALUES (?, ?)
    
  2. 型安全な自動生成

    • SQLから直接型安全なGoのメソッドを生成
    • パフォーマンスが非常に高い
  3. 柔軟なクエリ管理

    • 複雑なクエリも自由に記述可能
    • データベース操作の完全な制御

デメリット

  • ORMの機能は限定的
  • 関連モデルの操作が少し難しい

その他

Xorm,Entなどまだ他にもORMはありますが、情報が少なめなのと自分が触ったことがなかったので詳しいことは記述しないことにします。良さげな記事置いておきます。
Xorm:https://zenn.dev/a_ichi1/articles/5d9fbf3fbfea38
Ent:https://zenn.dev/tkb/articles/d1e6e3b7d62051

結局何がいいの!

ORM名 型安全性 特徴 メリット デメリット
GORM 最も人気のあるGoのORM 簡単操作、機能豊富、自動マイグレーション パフォーマンスがやや低い、学習コストが高め
SQLBoiler コード生成型、型安全性に特化 高速実行、型チェック可能、スキーマ変更に容易に対応 初期設定が複雑、スキーマ変更のたびにコード再生成が必要
SQLc SQLを直接記述して型安全なコードを生成 SQLの柔軟性、パフォーマンス高、複雑なクエリに対応 ORM特有の自動化機能が少ない、リレーション操作がやや面倒
Ent 型安全でモダンなORM スキーマをGoコードで定義、マイグレーション機能内蔵、エラーを最小化 学習コストが高い、シンプルなプロジェクトには過剰な機能
XORM 軽量で使いやすいGo用のORM 簡単なAPI、高速なプロトタイピング 型安全性が低い、大規模プロジェクトや複雑なリレーションには不向き

何にチャレンジしたいかによって分けるのがいいと思いますが、初めてならgormが参考記事も多くて使いやすと個人的に思います。
今自分の個人開発はsqlboilerを使って実装中なのですが、自動生成が楽しいです(?)
型安全やパフォーマンスも考えられるレベルになるよう、チョットワカルからケッコウワカルに進化していきたいと思います!それでは!

Discussion