模型是 GORM 的核心概念。一个 Go 结构体对应一张数据库表,结构体字段对应表字段。理解模型定义规则,是用好 GORM 的第一步。
最简单的模型:
type User struct {
ID uint
Name string
Age int
}
这个结构体会映射成一张 users 表:
CREATE TABLE `users` (
`id` bigint unsigned AUTO_INCREMENT,
`name` longtext,
`age` bigint,
PRIMARY KEY (`id`)
);
GORM 的映射规则:
ID 字段自动成为主键GORM 提供了一个内置的 gorm.Model 结构体:
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
嵌入它就自动有了这些字段:
type User struct {
gorm.Model
Name string
Age int
}
等价于:
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
Age int
}
DeletedAt 字段让模型支持软删除,删除操作只会设置时间戳而不是真正删除记录。
GORM 有很多默认约定,减少配置工作:
名为 ID 的字段自动成为主键:
type User struct {
ID uint // 主键
Name string
}
也可以用其他字段名,但需要显式标注:
type User struct {
UserID uint `gorm:"primaryKey"`
Name string
}
默认表名是结构体名的蛇形复数:
type User struct {} // → users
type OrderItem struct {} // → order_items
自定义表名:
func (User) TableName() string {
return "app_users"
}
字段名转蛇形:
type User struct {
FirstName string // → first_name
LastName string // → last_name
}
名为 CreatedAt、UpdatedAt、DeletedAt 的字段会自动管理:
CreatedAt - 创建记录时自动设置UpdatedAt - 更新记录时自动更新DeletedAt - 软删除时设置| Go 类型 | 数据库类型 |
|---|---|
| int, int32 | int |
| int64 | bigint |
| uint, uint32 | int unsigned |
| uint64 | bigint unsigned |
| float32 | float |
| float64 | double |
| string | varchar(191) 或 longtext |
| bool | tinyint(1) |
| time.Time | datetime |
| []byte | blob |
string 类型默认映射为 varchar(191),可以通过标签指定长度:
type User struct {
Name string `gorm:"size:100"` // varchar(100)
Bio string `gorm:"type:text"` // text
}
数据库字段允许 NULL 时,用指针类型:
type User struct {
Name string // NOT NULL
Email *string // 允许 NULL
}
或者用 sql.NullXxx 类型:
import "database/sql"
type User struct {
Name string
Age sql.NullInt64
Bio sql.NullString
Active sql.NullBool
CreatedAt sql.NullTime
}
指针类型更简洁,sql.NullXxx 可以区分 NULL 和零值。
有些字段不需要存数据库:
type User struct {
ID uint
Name string
Password string
Confirm string `gorm:"-"` // 忽略,不映射
}
gorm:"-" 标签让 GORM 完全忽略这个字段。
字段只允许读取,不允许写入:
type User struct {
ID uint
Name string
CreatedAt time.Time `gorm:"<-:create"` // 只在创建时写入
UpdatedAt time.Time `gorm:"<-:update"` // 只在更新时写入
ViewCount int `gorm:"->:false"` // 只读,不写入
}
模型可以定义方法,GORM 会在特定时机调用:
type User struct {
ID uint
Name string
Password string
}
// 创建前自动加密密码
func (u *User) BeforeCreate(tx *gorm.DB) error {
if u.Password != "" {
u.Password = hashPassword(u.Password)
}
return nil
}
这些方法叫钩子函数,后面章节会详细介绍。
一个项目通常有多个模型:
type User struct {
gorm.Model
Name string
Email string `gorm:"uniqueIndex"`
}
type Post struct {
gorm.Model
Title string
Content string
UserID uint
User User
}
type Comment struct {
gorm.Model
Content string
PostID uint
Post Post
UserID uint
User User
}
模型之间通过外键关联,GORM 会自动处理。
模型定义的核心要点:
gorm.Model 提供常用字段gorm:"-" 忽略字段理解这些基础,就能定义出符合业务需求的模型。下一章详细介绍字段类型和标签。