Go言語

Goで始めるGORM v2入門:インストールからCRUD・マイグレーションまで

ⓘ本ページはプロモーションが含まれています

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


スポンサードリンク

1. Go モジュールでのインストール

Go Modules を利用すれば依存関係が go.mod に自動で記録され、ビルド再現性が保証されます。過去の記事では固定バージョン(v1.25.0)を指定していましたが、常に最新リリースを取得したい場合は次の手順がおすすめです。

  • latestモジュールが解決できる最新版(GitHub のリリースページの最新タグ)を指します。
  • go mod tidy は未使用の依存関係を削除し、必要なパッケージだけを取得するため、手動でバージョン番号を書く必要がなくなります。

参考: GORM のリリース一覧は https://github.com/go-gorm/gorm/releases で確認できます。

Go 1.17 以降の推奨インストール方法

Go 1.17 からは go get がビルド時に依存関係を取得する目的だけで使われ、バイナリインストール(CLI ツール等)には go install pkg@version が推奨されています。GORM はライブラリなので go get の代わりに上記の モジュール宣言+go mod tidy を利用してください。


2. バージョニングの誤解を防ぐ

GORM v2 は モジュールパスが gorm.io/gorm のままで、バージョン番号に v2 が付かない という特殊なバージョニング方式です。そのため、公式サイトの「Versioning」ページで説明されている通り、メジャーバージョンはリポジトリタグだけで管理されています。以下のリンクで詳細を確認できます。

この情報を踏まえて、go.mod に記載されるバージョンは v1.xx.x(例:v1.25.4)ですが、実際には GORM v2 系 の機能が提供されています。


3. エラーハンドリングの統一方針

記事内では log.Fatalfpanic が混在していました。プロダクションコードでは エラーはロガーに委ねて呼び出し元へ返す、または コンテキストに紐付けた適切なログレベルで記録する ことがベストプラクティスです。

上記ヘルパーを利用した例です。

  • log.Fatalf のようにプロセスを即終了させる 代わりに、エラーは呼び出し側でハンドリングできるように返します。
  • テストやリトライロジックが必要な場面でも同一のインターフェースで扱えるため、コード全体の可読性と保守性が向上します。

データベース接続設定

データベースごとの DSN(Data Source Name)の書式は異なりますが、gorm.Open(driver, &gorm.Config{}) で統一的に接続できます。以下では PostgreSQL / MySQL / SQLite の実装例を示し、先ほどのエラーハンドリングヘルパーを適用しています。

PostgreSQL

PostgreSQL は標準的なキーバリュー形式の DSN が推奨されます。環境変数で管理すると CI/CD との相性が良くなるため、コード例では os.Getenv を併用しています。

  • sslmode=disable はローカル開発向けです。本番環境では必ず TLS を有効にしてください。
  • 環境変数 を利用することで、コードのハードコーディングを回避し、設定変更がデプロイなしで可能になります。

MySQL

MySQL の DSN は username:password@protocol(address)/dbname?param=value 形式です。文字エンコーディングやタイムゾーンに注意してください。

  • charset=utf8mb4 は絵文字や多言語対応に必須です。
  • parseTime=Trueloc=Local がないと、time.Time のマッピングが期待通りにならないことがあります。

SQLite(ファイル / メモリ)

SQLite は軽量でテスト向きです。ファイル保存かインメモリかを引数で切り替えられるようにラッパー関数を用意しています。

  • テストコードでは ConnectSQLiteMemory を利用すると、外部依存が無く高速に実行できます。

モデル定義と基本 CRUD 操作

GORM のモデルは 構造体タグ でテーブルスキーマを宣言します。以下の例では主要なタグ(primaryKey・size・uniqueIndex 等)を網羅し、JSON エンコード時の挙動も示しています。

構造体タグの書き方

  • primaryKey は自動的にインデックス化されます。
  • sizenot null はテーブル作成時にそのまま反映され、マイグレーションの手間が省けます。
  • omitempty により JSON へシリアライズするときにゼロ値フィールドは除外されます。

統一された CRUD 実装例

以下では先ほど作成した logger.Error ヘルパーを用い、エラーはすべて呼び出し元へ返しています。これにより テストやリトライロジック が容易になります。

  • db.Model(&User{}) を使うことで、インスタンスを生成せずに対象テーブルだけ指定できます。
  • すべての関数が error を返すため、サービス層やハンドラで一元的にエラーハンドリングが可能です。

クエリビルダーの活用

GORM のクエリビルダーは メソッドチェーン によって柔軟かつ安全に SQL を組み立てられます。以下ではページング、集計、特定カラム抽出を例示し、コード前に簡単な導入文を付けています。

ページングと並び替え

ユーザー一覧を年齢フィルタ付きで取得するケースです。Where のプレースホルダは SQL インジェクション対策になります。

  • Order に複数カラムを渡すことも可能です(例: "age ASC, name DESC")。

カラムだけ抽出する Pluck と集計クエリ

以下はメールアドレスのリスト取得と、年齢別ユーザー数の集計例です。

  • Pluck は余分な構造体を定義せずに単一列だけ取得でき、コードがすっきりします。
  • 集計結果は Scan で好きな構造体へマッピング可能です。

アソシエーションとフック

リレーションやライフサイクルフックはモデル層の責務を高めます。以下では Has One / Has Many, Belongs To / Many‑to‑Many の宣言方法、Preload による N+1 問題回避、そしてパスワードハッシュ化やキャッシュ削除といったフック実装例を示します。

リレーションの定義

User 側にリレーションフィールドを追加すると、GORM が自動で結合情報を認識します。

  • Has OneuniqueIndex が付いた外部キーで 1 対 1 の関係を表します。
  • Has Many はスライス型フィールドで 1 対 多の関係を示し、UserID が自動的に外部キーになります。
  • Many‑to‑Manymany2many:テーブル名; タグで結合テーブル名を明示します。

Preload による事前ロード

  • Preload の第2引数は条件付きロードが可能です。上記例ではタイトルに「GORM」を含む投稿だけを事前取得しています。

ライフサイクルフックの実装例

以下はパスワードハッシュ化とキャッシュ削除という、副作用処理 をモデル側で完結させる典型的なパターンです。

  • フックは *gorm.DB を受け取るので、トランザクション内での追加処理が容易です。
  • エラーはフック自体から返すことで、GORM がロールバックやエラーハンドリングを自動で行います。

マイグレーション・ロギング・テスト

開発フェーズと本番環境ではマイグレーションの扱い方が異なります。ここでは AutoMigrate の利用シーン、ロガー設定、そして SQLite in‑memory を使った単体テスト のベストプラクティスを紹介します。

AutoMigrate と本番マイグレーション

  • 推奨フロー
  • ローカル・ステージング環境で AutoMigrate を実行し、スキーマの変化を確認。
  • 本番リリース時は golang-migrate/migrate 等の外部マイグレーションツールで SQL ファイル を管理し、手動または CI に組み込んで適用する。
  • カラム削除や型変更はデータロスリスクが高いため、必ずバックアップと検証を行う。

ロガー設定とデバッグモード

GORM のロガーは標準ロガーだけでなく、zap, logrus など任意のロギングライブラリに差し替え可能です。以下は標準ロガーでスロークエリを可視化する例です。

  • 本番 では LogLevel: logger.Warn または logger.Error に設定し、ログ量を抑えると同時に重要な警告だけが出力されます。
  • SlowThreshold を適切に調整することでパフォーマンスボトルネックの早期発見が可能です。

SQLite in‑memory を使ったユニットテスト

外部データベースに依存しないテストは CI の安定性を高めます。以下は testing パッケージだけで完結するサンプルです。

  • テストは 状態を持たない SQLite メモリ DB 上で実行され、テストケースごとにクリーンな環境が保証されます。
  • logger.Error を使用しているため、エラーログが標準出力へ流れ、デバッグが容易です。

まとめ

  1. インストールはモジュール宣言+go mod tidyで最新版を取得し、バージョン固定による陳腐化リスクを回避します。
  2. バージョニングは GORM v2 が gorm.io/gorm に統合されている点に注意し、公式のバージョニングページへのリンクを添えて誤解防止を行いました。
  3. エラーハンドリングは ロガーで記録しエラーを返す 形に統一し、paniclog.Fatalf の混在を排除しました。
  4. 各データベース(PostgreSQL・MySQL・SQLite)の接続コードは環境変数活用とヘルパー関数で簡潔化し、テスト容易性を向上させました。
  5. モデル定義・CRUD・クエリビルダーのサンプルは 統一されたロガーヘルパー を使用し、実務に即した形に整理しました。
  6. アソシエーションとフックの実装例で リレーション宣言副作用処理(ハッシュ化・キャッシュ削除)を示し、モデル層の責務を明確化しました。
  7. 開発時は AutoMigrate、本番は外部マイグレーションツールと組み合わせるベストプラクティス、ロガー設定のチューニングポイント、そして SQLite in‑memory テスト の具体例を提供しました。

これらの手順とコードパターンをプロジェクトに取り入れれば、GORM を安全・効率的に運用できるだけでなく、将来的なバージョンアップやテスト自動化にも柔軟に対応できます。ぜひ実際にコードを書きながら試してみてください。

スポンサードリンク

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


-Go言語