入门指南

声明模型

qianmoQqianmoQ· 更新于 2026-09-23· 阅读 14 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

GORM 通过将 Go 结构体映射到数据库表来简化数据库交互。理解如何在 GORM 中声明模型是充分利用其全部功能的基础。

声明模型

模型使用普通结构体定义。这些结构体可以包含基本 Go 类型的字段、这些类型的指针或别名,甚至可以是自定义类型,只要它们实现了 database/sql 包中的 Scanner 和 Valuer 接口。

考虑以下 User 模型示例:

type User struct {
  ID           uint           
  Name         string         
  Email        *string        
  Age          uint8          
  Birthday     *time.Time     
  MemberNumber sql.NullString 
  ActivatedAt  sql.NullTime   
  CreatedAt    time.Time      
  UpdatedAt    time.Time      
  ignored      string         
}

在此模型中:

  • 直接使用了 uint、string 和 uint8 等基本数据类型。
  • *string 和 *time.Time 等类型的指针表示可为空的字段。
  • 来自 database/sql 包的 sql.NullString 和 sql.NullTime 用于需要更多控制的可为空字段。
  • CreatedAt 和 UpdatedAt 是特殊字段,GORM 会在记录创建或更新时自动填充当前时间。
  • 未导出的字段(以小写字母开头的字段)不会被映射。

除了 GORM 模型声明的基本功能之外,重要的是要强调通过 serializer 标签对序列化的支持。此功能增强了从数据库存储和检索数据的灵活性,特别是对于需要自定义序列化逻辑的字段,详见 Serializer 的详细说明。

约定

  1. 主键:GORM 使用名为 ID 的字段作为每个模型的默认主键。
  2. 表名:默认情况下,GORM 将结构体名称转换为 snake_case 并将其变为复数形式作为表名。例如,User 结构体在数据库中变为 users,GormUserName 变为 gorm_user_names。
  3. 列名:GORM 自动将结构体字段名转换为 snake_case 作为数据库中的列名。
  4. 时间戳字段:GORM 使用名为 CreatedAt 和 UpdatedAt 的字段来自动跟踪记录的创建时间和更新时间。

遵循这些约定可以大大减少你需要编写的配置或代码量。然而,GORM 也具有灵活性,允许你在默认约定不满足需求时进行自定义。你可以在 GORM 的 约定 文档中了解更多关于自定义这些约定的信息。

gorm.Model

GORM 提供了一个名为 gorm.Model 的预定义结构体,其中包含常用的字段:


type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}
  • 嵌入到你的结构体中:你可以直接将 gorm.Model 嵌入到你的结构体中以自动包含这些字段。这对于在不同模型之间保持一致性以及利用 GORM 的内置约定非常有用,参见 嵌入结构体。
  • 包含的字段:
    • ID:每条记录的唯一标识符(主键)。
    • CreatedAt:记录创建时自动设置为当前时间。
    • UpdatedAt:记录更新时自动更新为当前时间。
    • DeletedAt:用于软删除(将记录标记为已删除,而不会实际将其从数据库中移除)。

高级用法

字段级权限

导出的字段在使用 GORM 进行 CRUD 操作时拥有全部权限,GORM 允许你通过标签更改字段级权限,因此你可以将字段设置为只读、只写、仅创建、仅更新或忽略。

注意 忽略的字段在使用 GORM Migrator 创建表时不会被创建。

type User struct {
  Name string `gorm:"<-:create"` 
  Name string `gorm:"<-:update"` 
  Name string `gorm:"<-"`        
  Name string `gorm:"<-:false"`  
  Name string `gorm:"->"`        
  Name string `gorm:"->;<-:create"` 
  Name string `gorm:"->:false;<-:create"` 
  Name string `gorm:"-"`            
  Name string `gorm:"-:all"`        
  Name string `gorm:"-:migration"`  
}

创建/更新时间/Unix(毫秒/纳秒)秒跟踪

GORM 按照约定使用 CreatedAt 和 UpdatedAt 来跟踪创建/更新时间,如果定义了这些字段,GORM 会在创建/更新时设置 当前时间。

要使用不同名称的字段,你可以通过标签 autoCreateTime、autoUpdateTime 来配置这些字段。

如果你更倾向于保存 UNIX(毫秒/纳秒)秒数而不是时间,你只需将字段的数据类型从 time.Time 更改为 int。

type User struct {
  CreatedAt time.Time 
  UpdatedAt int       
  Updated   int64 `gorm:"autoUpdateTime:nano"` 
  Updated   int64 `gorm:"autoUpdateTime:milli"`
  Created   int64 `gorm:"autoCreateTime"`      
}

嵌入结构体

对于匿名字段,GORM 会将其字段包含到其父结构体中,例如:

type Author struct {
  Name  string
  Email string
}

type Blog struct {
  Author
  ID      int
  Upvotes int32
}

type Blog struct {
  ID      int64
  Name    string
  Email   string
  Upvotes int32
}

对于普通结构体字段,你可以使用标签 embedded 来嵌入它,例如:

type Author struct {
  Name  string
  Email string
}

type Blog struct {
  ID      int
  Author  Author `gorm:"embedded"`
  Upvotes int32
}

type Blog struct {
  ID    int64
  Name  string
  Email string
  Upvotes  int32
}

你还可以使用标签 embeddedPrefix 为嵌入字段的数据库名称添加前缀,例如:

type Blog struct {
  ID      int
  Author  Author `gorm:"embedded;embeddedPrefix:author_"`
  Upvotes int32
}

type Blog struct {
  ID          int64
  AuthorName  string
  AuthorEmail string
  Upvotes     int32
}

字段标签

声明模型时标签是可选的,GORM 支持以下标签:
标签不区分大小写,但推荐使用 camelCase。如果使用多个标签,
它们应该用分号(;)分隔。对解析器具有特殊含义的字符
可以使用反斜杠(\)进行转义,从而可以用作参数值。

标签名描述
column列的数据库名称
type列数据类型,优先使用兼容的通用类型,例如:bool、int、uint、float、string、time、bytes,适用于所有数据库,并可与其他标签一起使用,如 not null、size、autoIncrement……同时支持指定数据库数据类型,如 varbinary(8),使用指定数据库数据类型时,需要是完整的数据库数据类型,例如:MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT
serializer指定序列化器,用于数据的序列化和反序列化到数据库,例如:serializer:json/gob/unixtime
size指定列数据大小/长度,例如:size:256
primaryKey指定列为主键
unique指定列为唯一
default指定列默认值
precision指定列精度
scale指定列小数位数
not null指定列为 NOT NULL
autoIncrement指定列自动递增
autoIncrementIncrement自动递增步长,控制连续列值之间的间隔
embedded嵌入该字段
embeddedPrefix嵌入字段的列名前缀
autoCreateTime创建时跟踪当前时间,对于 int 字段,将跟踪 unix 秒,使用值 nano/milli 跟踪 unix 纳秒/毫秒,例如:autoCreateTime:nano
autoUpdateTime创建/更新时跟踪当前时间,对于 int 字段,将跟踪 unix 秒,使用值 nano/milli 跟踪 unix 纳秒/毫秒,例如:autoUpdateTime:milli
index创建带选项的索引,多个字段使用相同名称将创建复合索引,详见 索引
uniqueIndex与 index 相同,但创建唯一索引
check创建检查约束,例如:check:age > 13,详见 约束
<-设置字段的写权限,<-:create 仅创建字段,<-:update 仅更新字段,<-:false 无写权限,<- 创建和更新权限
->设置字段的读权限,->:false 无读权限
-忽略此字段,- 无读/写权限,-:migration 无迁移权限,-:all 无读/写/迁移权限
comment迁移时为字段添加注释

关联标签

GORM 允许通过标签为关联配置外键、约束、多对多表,详见 关联部分

GitHub tag (latest SemVer)

评论

登录后参与评论

正在加载评论…