如何在Gorm中声明非自动更新的Unix毫秒时间戳字段
实现业务触发式的毫秒级Unix时间戳字段(Gorm)
针对需求——仅在特定业务事件发生时更新毫秒级Unix时间戳字段,而非自动触发,这里提供几个便捷的自动化方案:
方案1:自定义字段类型(最优雅)
通过实现Gorm兼容的自定义字段类型,自动处理时间戳与数据库存储的转换,同时提供便捷的赋值方法:
import ( "database/sql/driver" "time" ) // UnixMilliTimestamp 自定义毫秒级Unix时间戳类型 type UnixMilliTimestamp int64 // Value 实现driver.Valuer接口,将类型转换为数据库可接受的格式 func (t UnixMilliTimestamp) Value() (driver.Value, error) { return int64(t), nil } // Scan 实现sql.Scanner接口,将数据库读取的值转换为自定义类型 func (t *UnixMilliTimestamp) Scan(value interface{}) error { switch v := value.(type) { case int64: *t = UnixMilliTimestamp(v) case time.Time: *t = UnixMilliTimestamp(v.UnixMilli()) default: return nil } return nil } // SetCurrent 快速设置为当前时间的毫秒级时间戳 func (t *UnixMilliTimestamp) SetCurrent() { *t = UnixMilliTimestamp(time.Now().UnixMilli()) }
在模型中使用该类型:
type YourModel struct { // 其他字段... BusinessUpdatedAt UnixMilliTimestamp `gorm:"column:business_updated_at;type:bigint"` }
业务触发更新时,只需调用方法后保存:
var model YourModel db.First(&model, 1) // 假设通过ID查询模型 model.BusinessUpdatedAt.SetCurrent() db.Save(&model)
方案2:钩子+标记字段(适合需结合其他更新逻辑)
用int64字段配合Gorm的BeforeUpdate钩子,通过内部标记控制是否更新时间戳:
import "time" type YourModel struct { // 其他字段... BusinessUpdatedAt int64 `gorm:"column:business_updated_at;type:bigint"` shouldUpdateBizAt bool `gorm:"-"` // 不映射到数据库的标记字段 } // BeforeUpdate Gorm更新钩子,仅在标记为true时更新时间戳 func (m *YourModel) BeforeUpdate(tx *gorm.DB) error { if m.shouldUpdateBizAt { m.BusinessUpdatedAt = time.Now().UnixMilli() m.shouldUpdateBizAt = false // 重置标记,避免误触发 } return nil } // MarkBizUpdate 业务层调用此方法,标记需要更新时间戳 func (m *YourModel) MarkBizUpdate() { m.shouldUpdateBizAt = true }
使用方式:
var model YourModel db.First(&model, 1) model.MarkBizUpdate() // 可以同时修改其他字段,钩子会自动处理时间戳更新 model.OtherField = "new value" db.Save(&model)
方案3:直接调用Update方法(简单场景首选)
如果业务逻辑简单,无需额外封装,直接在触发时调用Gorm的Update方法设置当前毫秒戳:
import "time" // 直接更新指定字段 db.Model(&YourModel{}).Where("id = ?", 1).Update("business_updated_at", time.Now().UnixMilli()) // 也可以结合其他字段一起更新 db.Model(&YourModel{}).Where("id = ?", 1).Updates(map[string]interface{}{ "business_updated_at": time.Now().UnixMilli(), "other_field": "new value", })
内容的提问来源于stack exchange,提问作者alok
相关产品推荐
相关产品推荐

