【发布时间】:2019-10-09 10:29:02
【问题描述】:
我正在处理一个要求,其中我收到一个 JSON 对象,其中包含一个日期值作为字符串。我的任务是将 Date 对象存储在数据库中。
类似的东西:
{"start_date": "2019-05-29", "end_date": "2019-08-30"}
{"start_date": "2019-05-29", "end_date": null}
我已经实现了自定义Date 类型
type Date struct {
time.Time
}
我已经实现了 UnmarshalJSON 接口
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 接口以将 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()函数)
第二次。
repl_test=# select id, start_date from customer_brokers;
id | start_date
----+------------
1 | 2019-05-29
2 | <- start_date empty here..
【问题讨论】:
-
我不确定我是否理解您的问题,但如果您在实现
Scan方法时遇到问题,那是因为您使用的是非指针接收器。 -
感谢您的更正...问题是当我执行
DB.Create(&record)时,除非扫描仪接口已实现start_date和end_date在DB 中都出现(在上述情况下)为NULL。如果我实现了 Scanner 接口,我会在数据库中看到正确的值。问题是我不需要扫描仪界面。由于该项目只是在 DB 中转储记录.. 没有从 DB 中读取任何内容。 -
您的问题令人困惑。但标题似乎直截了当。
sql.Scanner和driver.Valuer是同一枚硬币的两个面,类似于json.Unmarshaler和json.Marshaler。也就是说,sql.Scanner用于从数据库读取值,driver.Valuer用于向数据库写入值。是否两者都需要取决于是否需要同时向数据库读取和写入数据。 -
@Flimzy,事情就是这样。如果你可以运行上面的代码 2 次。 1 次不使用 Scan 方法,2 次使用 Scan 方法,您会看到只有最后插入的记录在
start_date列中具有值2019-05-29。这是我的问题.. -
我还是不知道你在问什么。我已经在评论中回答了标题。您的其余问题似乎与标题无关。我想您在插入数据时遇到问题?对此(根据我上面的评论)最重要的是
Valuer接口。但是你没有包含相关代码,所以很难说它为什么不起作用。