go time.Time 零值处理的方式
1.在定义表结构式经常需要用到 time.Time 的类型, 例如:
PayTime time.Time json:"pay_time" gorm:"default:null; comment:用户支付时间"
如果在创建记录的时候,不想设置此字段,又不想数据库中插入 "0001-01-01T00:00:00Z",则可以在gorm tag 里加上 default:null; 解决问题
2.在接口返回数据时,由于查询出的数据必须绑定到结构体,所以也会出现
image.png
这个格式对前端同学不够友好,前端同学希望当没有时间时为null
当我试图用类型别名来重载 time 包中的 MarshalJSON() 时
image.png
会报:非本地方法不能重载,类型别名只能为本地包添加独有方法
image.png
经过一番苦思,最终通过修改 time 包的 MarshalJSON()方法来搞定:
if t.IsZero() {
return []byte("null"), nil
}
image.png
由于第一次改标准库,心里还有一点点慌......
最后在大神的指导下不改标准库的情况下完美解决了该问题
package pkg
import "time"
type MyTime time.Time
var emptyTime = MyTime{}
func (t MyTime) MarshalJSON() ([]byte, error) {
if t == emptyTime {
return []byte("null"), nil
}
realT := time.Time(t)//将 MyTime 类型转化为 time.Time类型
return realT.MarshalJSON()
}
附:解决这个问题的过程中,我弄清了类型别名和类型再定义相关的内容:
类型别名:
type A = B:A和B的类型是一样的,包括他们所拥有的方法,A可以调用B的方法,可以为基本类型添加自己的方法,但不能未远程包定义自己的方法
类型再定义:
Type C D:C和D是不同的类型,C不能调用D的方法,相当于完全重新定义一个类型,但是新旧类型之间可以相互转化,新类型转化为旧类型之后就可以调用旧类型的方法,所以可以实现类似多态的效果
另外判断是否是零值,可以用两种方式:
无法获取time.Time 的值时用:
nilTime := time.Time{}
可以获取到值时用:
t.IsZero()
所以下面这两种用法是一样的:
func (t MyTime) MarshalJSON() ([]byte, error) {
realT := time.Time(t)
if realT.IsZero() {
return []byte("null"), nil
}
return realT.MarshalJSON()
}
func (t MyTime) MarshalJSON() ([]byte, error) {
var emptyTime MyTime
if t == emptyTime {
return []byte("null"), nil
}
realT := time.Time(t)
return realT.MarshalJSON()
}