You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:53:30