mcpField
G
go-gorm-model

go-gorm-model

github.com/cristiano-pacheco开发1111 次安装1 天前更新
代码仓库

关于 go-gorm-model

根据 SQL 迁移生成 Go GORM 持久化模型的技能,面向编写数据库映射结构体的开发者。它规定字段类型、可空值、标签及文件布局的约定。

主要功能

  1. 01SQL 到 Go 字段映射
  2. 02可空字段使用指针类型
  3. 03GORM 索引和默认值标签
  4. 04JSONB 列映射
  5. 05模型布局与命名规范

适用场景

  1. 01根据数据库迁移创建模型
  2. 02将 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 持久化模型。

适用场景

  • 创建映射数据库表的持久化模型
  • 添加包含可空指针类型、索引、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,可空时使用 *uint64。
时间字段
  • TIMESTAMPTZ 列使用 time.Time(如 CreatedAt、UpdatedAt 等)。
  • 不需要显式列标签 — GORM 会按约定将 CreatedAt 映射为 created_at。
可空字段

可空列使用 Go 指针类型。绝不要使用 database/sql 类型(sql.NullString、sql.NullInt32 等)— 此代码库不使用这些类型。

SQL 可空类型Go 类型
TEXT / VARCHAR 可空*string
BIGINT 可空(值)*int64
BIGINT 可空(外键)*uint64
BOOLEAN 可空*bool
TIMESTAMPTZ 可空*time.Time

此代码库中的示例:

Description      *string  // nullable TEXT
PromotionalPrice *int64   // nullable BIGINT value
CategoryID       *uint64  // nullable BIGINT FK
SceneContext     *string  // nullable TEXT
列标签

不要添加 gorm:"column:..." 标签。GORM 会自动将 Go 字段名映射为 snake_case 列名(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 → 使用 []byte 和 gorm:"type:jsonb"
  • default 值 → 使用 gorm:"default:'value'"
Attributes   []byte `gorm:"type:jsonb"`
PrimaryColor string `gorm:"default:'#1d4ed8'"`
值类型与外键类型

BIGINT 并非总是 uint64。请根据语义区分:

  • 主键:uint64,带 gorm:"primarykey"
  • NOT NULL 外键:uint64
  • 可空外键:*uint64
  • 数值(价格、重量、尺寸、数量):int64 / *int64
  • 小整数(排序顺序、显示顺序):int
  • 布尔值:bool

生成步骤

  1. 确定模块和实体。
  2. 阅读迁移 SQL 文件,确认准确的表名和列定义。
  3. 创建 internal/modules/<module>/model/<entity>_model.go。
  4. 将每个 SQL 列映射为正确的 Go 字段名和类型。
  5. 对可空列使用指针类型。
  6. 仅在需要时添加 GORM 标签(索引、uniqueIndex、类型、默认值)。
  7. 为结构体和 TableName() 添加文档注释。
  8. 验证结构体字段顺序与迁移中的列顺序一致(便于阅读)。

类型映射指南

SQL 类型NOT NULL可空
BIGSERIAL PRIMARY KEYuint64 + gorm:"primarykey"—
BIGINT 外键uint64*uint64
BIGINT 值int64*int64
INTint*int
VARCHAR / TEXTstring*string
BOOLEANbool*bool
TIMESTAMPTZtime.Time*time.Time
JSONB[]byte + gorm:"type:jsonb"—

示例:简单模型

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"
}

示例:包含可空字段和 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"
}

关键规则

  • 不要定义独立函数:当文件包含带方法的结构体时,不要添加独立函数。请改用结构体上的私有方法。
  • 模型仅用于持久化,业务逻辑应放在用例中。
  • 不要在 HTTP DTO 响应中直接暴露 GORM 模型。
  • 字段名称和类型必须与 SQL 迁移保持一致。
  • 对可为空的列使用 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"
  • 可为空的列使用指针类型(*string、*int64、*uint64)
  • 不导入 database/sql,也不使用 SQL 可空类型
  • 除非必要,否则不使用显式的 gorm:"column:..." 标签
  • 在迁移中定义了索引或约束的地方添加相应标签(uniqueIndex、index)
  • PostgreSQL 专用列添加相应标签(type:jsonb、default:...)
  • TableName() 带有文档注释,并返回完全匹配的 SQL 表名
  • 不使用 json 标签

评论

支持 Markdown