← 返回文章列表

GORM 自动设置 MySQL 数据的创建和修改时间

Go
  • # go
  • # gorm
  • # mysql

使用 GORM 操作 MySQL 数据表时,经常会遇到一个很普通但很容易反复处理的问题:创建时间和更新时间应该由谁来设置?

常见做法有几种:使用 GORM 的约定字段、给自定义字段添加时间追踪标签、把时间更新交给数据库,或者直接嵌入 gorm.Model

使用默认支持字段

GORM 约定使用 CreatedAtUpdatedAt 来追踪记录的创建时间和更新时间。只要模型里定义了这两个字段,GORM 在创建和更新记录时就会自动填充当前时间。

type User struct {
    CreatedAt time.Time `gorm:"column:created_at;" json:"created_at"` // 创建时间
    UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`  // 更新时间
}

GORM 文档 中的说明是:如果定义了 CreatedAtUpdatedAt 字段,GORM 会在创建、更新时自动填充当前时间。

使用自定义字段

如果字段名不是 CreatedAtUpdatedAt,可以通过 autoCreateTimeautoUpdateTime 标签告诉 GORM 这些字段分别用于创建时间和更新时间。

type User struct {
    Created time.Time `gorm:"column:created;autoCreateTime" json:"created"`
    Updated time.Time `gorm:"column:updated;autoUpdateTime" json:"updated"` // 更新时间
}

这种方式适合数据库里已经有固定字段名,或者项目希望字段命名更贴近现有表结构的情况。

交给 MySQL 维护时间

也可以直接在数据库层设置 CURRENT_TIMESTAMP,让 MySQL 在插入和更新时维护时间。

`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

如果希望数据库负责这两个字段,结构体里可以把字段标记为只读,避免 GORM 写入时覆盖它们:

type User struct {
    CreatedAt time.Time `gorm:"column:created_at;<-:false" json:"created_at"` // 创建时间
    UpdatedAt time.Time `gorm:"column:updated_at;<-:false" json:"updated_at"` // 更新时间
}

<-:false 是 GORM 的字段级权限标签,表示允许读取,但禁止写入。这样应用侧仍然能读取时间字段,实际写入和更新时间由 MySQL 完成。

使用 gorm.Model

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
}

这种方式很方便,适合接受 GORM 默认字段设计的场景。不过如果你需要自定义字段名、JSON 标签、数据库列名,或者不需要软删除字段,手动定义字段会更直接。

gorm.Model 包含的字段包括:

  • ID:记录的主键。
  • CreatedAt:创建记录时自动设置。
  • UpdatedAt:更新记录时自动更新。
  • DeletedAt:用于软删除。

初始化结构体数据时,通常不要主动给这些自动时间字段设置值,让 GORM 或数据库按约定处理即可。

参考:GORM 模型定义