我正在处理要求,其中我收到一个包含日期值作为字符串的JSON对象。我的任务是将Date对象存储在数据库中。
这种东西:
{"start_date": "2019-05-29", "end_date": "2019-08-30"}
{"start_date": "2019-05-29", "end_date": null}
我已经实现了Custom
Date
类型type Date struct {
time.Time
}
我已经实现了UnmarshalJSON接口(interface)
func (d *Date) UnmarshalJSON(b []byte) (err error) {
if b[0] == '"' && b[len(b)-1] == '"' {
b = b[1 : len(b)-1]
}
// take care of null..
if len(b) == 0 || string(b) == "null" {
d.Time = time.Time{}
return
}
d.Time, err = time.Parse("2006-01-02", string(b))
return
}
还实现了Valuer接口(interface),以将Value返回给sql.Driver。
func (d Date) Value() (driver.Value, error) {
// check if the date was not set..
if d.Time.IsZero() {
return nil, nil
}
return d.Time.Format("2006-01-02"), nil
}
但是由于某种原因,直到 Date实现了Scanner界面,
像这样的东西:
func (d Date) Scan(b interface{}) (err error) {
...
return
}
问题:
ORM适配器(GORM)不在数据库中存储记录。有什么线索吗?
完整代码列出here
进一步详细说明
如果我两次运行上面的代码2,我会看到不同的行为,具体取决于是否存在Scan()函数。
1次:
数据库结果
repl_test=# select id, start_date from customer_brokers;
id | start_date
----+------------
1 | 2019-05-29
现在都很好..运行相同的代码..(注释了
Scan()
函数)第2次。
repl_test=# select id, start_date from customer_brokers;
id | start_date
----+------------
1 | 2019-05-29
2 | <- start_date empty here..
最佳答案
启用DB.LogMode(true)
将显示这两个查询
扫描:
[2019-10-16 14:03:34] [0.97ms] INSERT INTO "custom_brokers" ("created_at","updated_at","deleted_at","start_date","end_date") VALUES ('2019-10-16 14:03:34','2019-10-16 14:03:34',NULL,'2019-05-29',NULL) RETURNING "custom_brokers"."id"
未经扫描:
[2019-10-16 14:02:53] [0.76ms] INSERT INTO "custom_brokers" ("created_at","updated_at","deleted_at") VALUES ('2019-10-16 14:02:53','2019-10-16 14:02:53',NULL) RETURNING "custom_brokers"."id"
第二个显示了gorm完全忽略了模型中的另一列(嵌入式gorm模型除外)
调试之后,我尝试创建模型here,gorm检查该字段是否为
sql.Scanner
,然后设置IsNormal
字段,该字段用于查询创建阶段。如果该字段不是sql.Scanner
,则IsNormal
为false,因此被忽略here因此,您问题的答案是肯定的,即使您无需扫描
Scan
方法也必须实现。关于go - 是否需要与Valuer接口(interface)一起实现Scanner接口(interface),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58302137/