
Go Gorm Model
- 109 installs
- Updated July 22, 2026
- cristiano-pacheco/ai-tools
Generates GORM persistence models for a Go module with table mapping, nullable SQL types, timestamps, and relation fields.
About
Scaffolds a GORM model struct with a TableName method, nullable database/sql types, and timestamp/relation fields. A developer uses it when creating or updating persistence models.
- Generates <Entity>Model struct with TableName() method
- Handles nullable SQL types and timestamps
Go Gorm Model by the numbers
- 109 all-time installs (skills.sh)
- Ranked #41 of 98 Go skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cristiano-pacheco/ai-tools --skill go-gorm-modelAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 109 |
|---|---|
| Last updated | July 22, 2026 |
| Repository | cristiano-pacheco/ai-tools ↗ |
What it does
Generates GORM persistence models for a Go module with table mapping, nullable SQL types, timestamps, and relation fields.
Files
Go GORM Model
Generate GORM persistence models in internal/modules/<module>/model/.
When to Use
- Create persistence models mapping database tables
- Add structs with nullable pointer types, indexes, JSONB, defaults
- Map SQL migrations to Go structs
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:
1. package model 2. Imports ("time" only — add others only when strictly required) 3. Struct definition with doc comment 4. 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 TEXTColumn 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
1. Identify module and entity. 2. Read the migration SQL file and confirm the exact table name and column definitions. 3. Create internal/modules/<module>/model/<entity>_model.go. 4. Map each SQL column to the correct Go field name and type. 5. Use pointer types for nullable columns. 6. Add GORM tags only where needed (index, uniqueIndex, type, default). 7. Add doc comment to the struct and to TableName(). 8. 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