mcpField
G
go-gorm-model

go-gorm-model

github.com/cristiano-pacheco開発1111 回インストール1 日前に更新
リポジトリ

go-gorm-model について

SQLマイグレーションをもとにGoのGORM永続化モデルを生成するスキルです。データベース対応の構造体を作る開発者向けに、フィールド型、NULL許容、タグ、ファイル配置の規約を示します。

主な機能

  1. 01SQLからGoフィールドへの対応付け
  2. 02NULL許容フィールドのポインター型
  3. 03GORMのインデックスとデフォルトタグ
  4. 04JSONB列のマッピング
  5. 05モデルの配置と命名規則

活用シーン

  1. 01データベースマイグレーションからモデルを作成する
  2. 02NULL許容のSQL列をGoフィールドに対応付ける
  3. 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>" }

ファイル構成

次の順序で記述します。

  1. package model
  2. インポート("time" のみ — 厳密に必要な場合に限り、ほかのものを追加)
  3. ドキュメントコメント付きの構造体定義
  4. ドキュメントコメント付きの 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" を付けた []byte
  • default 値 → 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

生成手順

  1. モジュールとエンティティを特定します。
  2. マイグレーション SQL ファイルを読み、正確なテーブル名とカラム定義を確認します。
  3. internal/modules/<module>/model/<entity>_model.go を作成します。
  4. 各 SQL カラムを、適切な Go のフィールド名と型にマッピングします。
  5. NULL 許容列にはポインター型を使用します。
  6. 必要な場合に限り、GORM タグ(index、uniqueIndex、type、default)を追加します。
  7. 構造体と TableName() にドキュメントコメントを追加します。
  8. 可読性のため、構造体のフィールド順がマイグレーション内のカラム順と一致することを確認します。

型マッピングガイド

SQL 型NOT NULLNULL 許容
BIGSERIAL PRIMARY KEYgorm:"primarykey" を付けた uint64—
BIGINT 外部キーuint64*uint64
BIGINT 値int64*int64
INTint*int
VARCHAR / TEXTstring*string
BOOLEANbool*bool
TIMESTAMPTZtime.Time*time.Time
JSONBgorm:"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 タグを使用していない

コメント