go-gorm-model について
SQLマイグレーションをもとにGoのGORM永続化モデルを生成するスキルです。データベース対応の構造体を作る開発者向けに、フィールド型、NULL許容、タグ、ファイル配置の規約を示します。
主な機能
- 01SQLからGoフィールドへの対応付け
- 02NULL許容フィールドのポインター型
- 03GORMのインデックスとデフォルトタグ
- 04JSONB列のマッピング
- 05モデルの配置と命名規則
活用シーン
- 01データベースマイグレーションからモデルを作成する
- 02NULL許容のSQL列をGoフィールドに対応付ける
- 03インデックスとデフォルト値のGORMタグを追加する
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cristiano-pacheco/ ai-tools --skill go-gorm-modelインストール後、Claude Code で/go-gorm-modelを入力して読み込まれたか確認します。
詳細
Go GORM モデル
internal/modules/<module>/model/ に GORM の永続化モデルを生成します。
使用する場面
- データベースのテーブルに対応する永続化モデルを作成する
- NULL 許容のポインター型、インデックス、JSONB、デフォルト値を持つ構造体を追加する
- SQL マイグレーションを Go の構造体にマッピングする
パターン
モデルファイルは、次の配置と命名規則に従います。
- パス:
internal/modules/<module>/model/<entity>_model.go - パッケージ:
model - 構造体名:
<Entity>Model - TableName メソッド:
func (*<Entity>Model) TableName() string { return "<table_name>" }
ファイル構成
次の順序で記述します。
package model- インポート(
"time"のみ — 厳密に必要な場合に限り、ほかのものを追加) - ドキュメントコメント付きの構造体定義
- ドキュメントコメント付きの
TableName()メソッド
基本テンプレート
package model
import "time"
// EntityModel represents an entity in the database.
type EntityModel struct {
ID uint64 `gorm:"primarykey"`
Name string
CreatedAt time.Time
UpdatedAt time.Time
}
// TableName returns the table name for the entity model.
func (*EntityModel) TableName() string {
return "entities"
}
規約
ID と主キー
ID主キーフィールドにはuint64を使用し、必ずgorm:"primarykey"タグを付けます。- 外部キー(別のテーブルの主キーを参照するフィールド)にも、NOT NULL の場合は
uint64、NULL 許容の場合は*uint64を使用します。
時刻フィールド
TIMESTAMPTZ列(CreatedAt、UpdatedAtなど)にはtime.Timeを使用します。- 明示的なカラムタグは不要です。GORM は慣例に従って
CreatedAtをcreated_atにマッピングします。
NULL 許容フィールド
NULL 許容列にはGo のポインター型を使用します。database/sql 型(sql.NullString、sql.NullInt32 など)は使用しないでください。このコードベースでは使用されていません。
| SQL の NULL 許容型 | Go の型 |
|---|---|
TEXT / VARCHAR の NULL 許容 | *string |
BIGINT の NULL 許容(値) | *int64 |
BIGINT の NULL 許容(外部キー) | *uint64 |
BOOLEAN の NULL 許容 | *bool |
TIMESTAMPTZ の NULL 許容 | *time.Time |
このコードベースでの例:
Description *string // nullable TEXT
PromotionalPrice *int64 // nullable BIGINT value
CategoryID *uint64 // nullable BIGINT FK
SceneContext *string // nullable TEXT
カラムタグ
gorm:"column:..." タグは追加しないでください。GORM は Go のフィールド名を自動的にスネークケースのカラム名にマッピングします(ProductID → product_id、CreatedAt → created_at など)。特定の GORM 機能を宣言する場合に限り、タグを追加します。
次の場合に限り、タグを追加します。
gorm:"primarykey"— 主キーgorm:"uniqueIndex"/gorm:"uniqueIndex:name"— 一意制約gorm:"index"— 通常のインデックスgorm:"type:jsonb"— PostgreSQL の JSONB 列gorm:"default:'value'"— 列レベルのデフォルト値gorm:"->;column:name"— 計算される読み取り専用の仮想列
インデックスと制約のタグ
フィールドにインラインでインデックスを宣言します。
Slug string `gorm:"uniqueIndex"`
ProductID uint64 `gorm:"index"`
// Named composite unique index (both fields must share the same name)
CollectionID uint64 `gorm:"uniqueIndex:idx_collection_product"`
ProductID uint64 `gorm:"uniqueIndex:idx_collection_product"`
PostgreSQL 固有の型
JSONB→gorm:"type:jsonb"を付けた[]bytedefault値 →gorm:"default:'value'"
Attributes []byte `gorm:"type:jsonb"`
PrimaryColor string `gorm:"default:'#1d4ed8'"`
値の型と外部キーの型
BIGINT が常に uint64 とは限りません。意味に応じて使い分けます。
- 主キー:
gorm:"primarykey"を付けたuint64 - NOT NULL の外部キー:
uint64 - NULL 許容の外部キー:
*uint64 - 数値(価格、重量、サイズ、数量):
int64/*int64 - 小さい整数(並び順、表示順):
int - ブール値:
bool
生成手順
- モジュールとエンティティを特定します。
- マイグレーション SQL ファイルを読み、正確なテーブル名とカラム定義を確認します。
internal/modules/<module>/model/<entity>_model.goを作成します。- 各 SQL カラムを、適切な Go のフィールド名と型にマッピングします。
- NULL 許容列にはポインター型を使用します。
- 必要な場合に限り、GORM タグ(
index、uniqueIndex、type、default)を追加します。 - 構造体と
TableName()にドキュメントコメントを追加します。 - 可読性のため、構造体のフィールド順がマイグレーション内のカラム順と一致することを確認します。
型マッピングガイド
| SQL 型 | NOT NULL | NULL 許容 |
|---|---|---|
BIGSERIAL PRIMARY KEY | gorm:"primarykey" を付けた uint64 | — |
BIGINT 外部キー | uint64 | *uint64 |
BIGINT 値 | int64 | *int64 |
INT | int | *int |
VARCHAR / TEXT | string | *string |
BOOLEAN | bool | *bool |
TIMESTAMPTZ | time.Time | *time.Time |
JSONB | gorm:"type:jsonb" を付けた []byte | — |
例:シンプルなモデル
package model
import "time"
// CategoryModel represents a category in the database.
type CategoryModel struct {
ID uint64 `gorm:"primarykey"`
Name string `gorm:"uniqueIndex"`
Slug string `gorm:"uniqueIndex"`
ShowInMenu bool
CreatedAt time.Time
UpdatedAt time.Time
}
// TableName returns the table name for the category model.
func (*CategoryModel) TableName() string {
return "categories"
}
例:NULL 許容フィールドと JSONB を含むモデル
package model
import "time"
// ProductModel represents a product in the database.
type ProductModel struct {
ID uint64 `gorm:"primarykey"`
Title string
Description string
Price int64
PromotionalPrice *int64
SKU string `gorm:"uniqueIndex"`
Status string
WeightGrams *int64
WidthCm *int64
LengthCm *int64
HeightCm *int64
StockQuantity int64
CategoryID *uint64
Attributes []byte `gorm:"type:jsonb"`
CreatedAt time.Time
UpdatedAt time.Time
}
// TableName returns the table name for the product model.
func (*ProductModel) TableName() string {
return "products"
}
例:結合テーブル(複合一意インデックス)
package model
import "time"
// CollectionProductModel represents the many-to-many relationship
// between collections and products.
type CollectionProductModel struct {
ID uint64 `gorm:"primarykey"`
CollectionID uint64 `gorm:"uniqueIndex:idx_collection_product"`
ProductID uint64 `gorm:"uniqueIndex:idx_collection_product"`
CreatedAt time.Time
}
// TableName returns the table name for the collection product model.
func (*CollectionProductModel) TableName() string {
return "collection_products"
}
例:デフォルト値を持つモデル
package model
import "time"
// ProfileModel represents the business profile in the database.
type ProfileModel struct {
ID uint64 `gorm:"primarykey"`
BusinessName string
WhatsAppPhone string
LogoPath string
LogoMimeType string
PrimaryColor string `gorm:"default:'#1d4ed8'"`
AccentColor string `gorm:"default:'#16a34a'"`
CreatedAt time.Time
UpdatedAt time.Time
}
// TableName returns the table name for the profile model.
func (*ProfileModel) TableName() string {
return "profiles"
}
重要なルール
- 単独の関数を追加しないでください:ファイルにメソッドを持つ構造体がある場合、単独の関数を追加しないでください。代わりに、構造体のプライベートメソッドを使用してください。
- モデルは永続化のみに使用し、ビジネスロジックはユースケースに記述してください。
- GORM モデルを HTTP DTO のレスポンスで直接公開しないでください。
- フィールド名と型を SQL マイグレーションに合わせてください。
- NULL を許容するカラムには Go のポインター型(
*string、*int64、*uint64)を使用してください。database/sqlの型は使用しないでください。 - GORM の規約でマッピングを処理できない場合を除き、
gorm:"column:..."タグを追加しないでください。 - GORM モデルに
jsonタグを使用しないでください。 - モジュール内のモデルパッケージのみを使用してください(
internal/modules/<module>/model)。 - 構造体と
TableName()メソッドには、必ずドキュメントコメントを追加してください。 - 対応するマイグレーションを更新せずに、既存のカラム名やテーブル名を変更しないでください。
チェックリスト
- ファイルの場所が
internal/modules/<module>/model/<entity>_model.go - 構造体名が
<Entity>Modelで、ドキュメントコメントがある -
ID uint64にgorm:"primarykey"が設定されている - NULL を許容するカラムにポインター型(
*string、*int64、*uint64)を使用している -
database/sqlのインポートや SQL の NULL 許容型を使用していない - 必須の場合を除き、明示的な
gorm:"column:..."タグを使用していない - マイグレーションで定義されている箇所にインデックス/制約のタグ(
uniqueIndex、index)がある - PostgreSQL 固有のカラムにタグ(
type:jsonb、default:...)が設定されている -
TableName()にドキュメントコメントがあり、正確な SQL テーブル名を返す -
jsonタグを使用していない
コメント
Markdown 対応