go-gorm-model
9
总安装量
9
周安装量
#33444
全站排名
安装命令
npx skills add https://github.com/cristiano-pacheco/ai-tools --skill go-gorm-model
Agent 安装分布
opencode
9
gemini-cli
9
claude-code
9
amp
9
github-copilot
9
codex
9
Skill 文档
Go GORM Model
Generate GORM persistence models in internal/modules/<module>/model/.
Pattern
Model files must follow this location and naming:
- Path:
internal/modules/<module>/model/<entity>_model.go - Package:
model - Struct name:
<Entity>Model - TableName method:
func (*<Entity>Model) TableName() string { return "<table_name>" }
File Structure
Use this order:
package model- Imports (
"time"only â add others only when strictly required) - Struct definition with doc comment
TableName()method with doc comment
Base Template
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"
}
Conventions
IDs and Primary Keys
- Use
uint64for theIDprimary key field, always taggedgorm:"primarykey". - Foreign key fields (references to another table’s PK) also use
uint64when NOT NULL, or*uint64when nullable.
Time Fields
- Use
time.TimeforTIMESTAMPTZcolumns (CreatedAt,UpdatedAt, etc.). - No explicit column tag needed â GORM maps
CreatedAtâcreated_atby convention.
Nullable Fields
Use Go pointer types for nullable columns. Never use database/sql types (sql.NullString, sql.NullInt32, etc.) â those are not used in this codebase.
| SQL nullable type | Go type |
|---|---|
TEXT / VARCHAR nullable |
*string |
BIGINT nullable (value) |
*int64 |
BIGINT nullable (FK) |
*uint64 |
BOOLEAN nullable |
*bool |
TIMESTAMPTZ nullable |
*time.Time |
Examples from this codebase:
Description *string // nullable TEXT
PromotionalPrice *int64 // nullable BIGINT value
CategoryID *uint64 // nullable BIGINT FK
SceneContext *string // nullable TEXT
Column Tags
Do NOT add gorm:"column:..." tags. GORM automatically maps Go field names to snake_case column names (ProductID â product_id, CreatedAt â created_at, etc.). Only add tags when there is a specific GORM feature to declare.
Add tags only for:
gorm:"primarykey"â primary keygorm:"uniqueIndex"/gorm:"uniqueIndex:name"â unique constraintsgorm:"index"â regular indexesgorm:"type:jsonb"â PostgreSQL JSONB columnsgorm:"default:'value'"â column-level defaultsgorm:"->;column:name"â computed/read-only virtual columns
Index and Constraint Tags
Declare indexes inline on the field:
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-Specific Types
JSONBâ[]bytewithgorm:"type:jsonb"defaultvalues âgorm:"default:'value'"
Attributes []byte `gorm:"type:jsonb"`
PrimaryColor string `gorm:"default:'#1d4ed8'"`
Value Types vs FK Types
BIGINT is not always uint64. Distinguish by semantics:
- Primary key:
uint64withgorm:"primarykey" - Foreign key NOT NULL:
uint64 - Foreign key nullable:
*uint64 - Numeric value (price, weight, size, quantity):
int64/*int64 - Small integer (sort order, display order):
int - Boolean:
bool
Generation Steps
- Identify module and entity.
- Read the migration SQL file and confirm the exact table name and column definitions.
- Create
internal/modules/<module>/model/<entity>_model.go. - Map each SQL column to the correct Go field name and type.
- Use pointer types for nullable columns.
- Add GORM tags only where needed (index, uniqueIndex, type, default).
- Add doc comment to the struct and to
TableName(). - Verify struct field order matches the column order in the migration (for readability).
Type Mapping Guide
| SQL Type | NOT NULL | Nullable |
|---|---|---|
BIGSERIAL PRIMARY KEY |
uint64 + gorm:"primarykey" |
â |
BIGINT FK |
uint64 |
*uint64 |
BIGINT value |
int64 |
*int64 |
INT |
int |
*int |
VARCHAR / TEXT |
string |
*string |
BOOLEAN |
bool |
*bool |
TIMESTAMPTZ |
time.Time |
*time.Time |
JSONB |
[]byte + gorm:"type:jsonb" |
â |
Example: Simple Model
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"
}
Example: Model with Nullable Fields and 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"
}
Example: Join Table (Composite Unique Index)
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"
}
Example: Model with Default Values
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"
}
Critical Rules
- No standalone functions: When a file contains a struct with methods, do not add standalone functions. Use private methods on the struct instead.
- Models are persistence only â business logic belongs in use cases.
- Do not expose GORM models directly in HTTP DTO responses.
- Keep field names and types aligned with SQL migrations.
- Use Go pointer types (
*string,*int64,*uint64) for nullable columns â neverdatabase/sqltypes. - Do NOT add
gorm:"column:..."tags unless GORM convention cannot handle the mapping. - Never use
jsontags on GORM models. - Use module-local model package only (
internal/modules/<module>/model). - Always add doc comments on the struct and
TableName()method. - Do not change existing column or table names without a corresponding migration update.
Checklist
- File at
internal/modules/<module>/model/<entity>_model.go - Struct named
<Entity>Modelwith doc comment -
ID uint64withgorm:"primarykey" - Nullable columns use pointer types (
*string,*int64,*uint64) - No
database/sqlimport or nullable SQL types - No explicit
gorm:"column:..."tags unless required - Index/constraint tags present where migration defines them (
uniqueIndex,index) - PostgreSQL-specific columns tagged (
type:jsonb,default:...) -
TableName()with doc comment returns exact SQL table name - No
jsontags