GORM自定义类型

文章介绍了在GORM中自定义时间类型以处理常见的日期时间格式,如2023-04-0812:12:12。通过实现`sql.Scanner`和`driver.Valuer`接口,使GORM能直接识别和转换字符串类型的时间。作者提供了一个DateTime类型的示例,并讨论了自定义类型在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GORM自定义类型

官网地址

官方也有一个用来收集自定义的类型的仓库:https://github.com/go-gorm/datatypes

场景

时间类型
初始的时间类型只有time.time类型,而我们习惯输入和展示的结构是形如 2023-04-08 12:12:12这种。
这种格式需要被程序转化为time.time类型被orm使用,从数据库查找的时候也需要做同样的转换。
// 我这里举个例子,当我收到json数据我会转成解析成如下结构体
type CreateOrderRequest struct {
	OrderId           int64          `json:"order_id"`
	PartnerId         int64          `json:"partner_id"`    //客户
	DateOrder         DateTime       `json:"date_order"`    //订购日期
	...
	Products          []OrderProduct `json:"products"`
	Note              string         `json:"note"`
}
// 其中有个我自定义的类型DateTime
type DateTime time.Time

var TimeFormats = []string{"2006-01-02 15:04:05", "20060102150405"}

func (t *DateTime) UnmarshalJSON(data []byte) (err error) {
	fmt.Println(string(data))
	// 空值不进行解析
	if len(data) == 2 {
		*t = DateTime(time.Time{})
		return
	}
	var now time.Time
	for _, format := range TimeFormats {
		// 指定解析的格式
		if now, err = time.ParseInLocation(format, string(data), time.Local); err == nil {
			*t = DateTime(now)
			return
		}
		// 指定解析的格式
		if now, err = time.ParseInLocation(`"`+format+`"`, string(data), time.Local); err == nil {
			*t = DateTime(now)
			return
		}
	}
	return
}
//当我在添加数据库时
// CreateOrder 创建订单
func CreateOrder(info global.CreateOrderRequest, login_user_id int64) (oid int64, err error) {
    ...
	order := model.SaleOrder{
		Name:              order_no,
		...
		DateOrder:         time.Time(info.DateOrder),
		...
	}
	if err = tx.Create(&order).Error; err != nil {
		tx.Rollback()
		return
	}
	...
}
//可以很方便的使用
//这种方式我比较推荐

使用自定义类型

我们可以自定义一个类型使得gorm可以直接识别字符串类型的时间格式,这里我只提供这种思路并不建议在实际情况中使用
//自定义的数据类型必须实现 Scanner 和 Valuer 接口,以便让 GORM 知道如何将该类型接收、保存到数据库

type DateTime string

// 实现 sql.Scanner 接口,Scan 将 value 扫描至
func (j *DateTime) Scan(value interface{}) error {
	*j = DateTime((value.(time.Time)).Format("2006-01-02 15:04:05"))
	return nil
}

// 实现 driver.Valuer 接口,Value 返回 json value
func (j DateTime) Value() (driver.Value, error) {
	return string(j), nil
}
//实现这两个接口方法之后我们就可以直接使用这个类型了
//查询时gorm就会直接为我们转成当前类型
type ResGroups1 struct {
    Id         int64
    Name       string
    CreateDate DateTime
}
var info ResGroups1
db.Table("res_groups").First(&info, 2)
//插入时我们就可以直接用字符串插入
type ResGroups1 struct {
    Name       string
    CreateDate DateTime
}
db.Table("res_groups").Create(&ResGroups1{Name: "123", CreateDate: "2023-03-09 06:27:45"})

最后

  • 自定义类型Github 仓库已经提供了date和time类型,但是我好像没找到datetime类型,所以自己尝试了下。
  • 没有在实战中使用,因为我现在也适应了直接使用time.time类型
  • 对于以前从PHP转go的我来说,一开始go的时间类型确实不太适应,但是慢慢的用多了之后倒是不觉得多麻烦了
  • 不局限于时间类型,其他很多gorm满足不了我们使用的时候,或者使用的时候需要经常来回处理的时候我们可以尝试自定义自己的类型以加快我们的开发速度

作者:沈强

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中亿丰数字科技集团有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值