未实现Scanner接口导致GORM无法存储自定义Date类型数据问题
为什么未实现Scanner接口时GORM无法存储记录?
我来帮你拆解这个问题的核心原因,其实和GORM的类型处理逻辑以及Go标准库的数据库交互规则密切相关:
首先得明确Go标准库中与数据库交互的两个核心接口:
driver.Valuer:负责将Go类型转换为数据库可接收的格式(对应写入数据库的场景)sql.Scanner:负责将数据库返回的结果转换为Go类型(对应查询数据库的场景)
你可能会疑惑:既然写入只需要Valuer,为什么没实现Scanner就存不了数据?这是因为GORM的内部逻辑有个关键前提:
GORM在识别模型字段的自定义类型时,会要求该类型同时实现sql.Scanner和driver.Valuer接口。它默认假设自定义类型需要支持双向的数据转换能力(既能写入数据库,也能从数据库读取)。
具体到你的场景:
- 当你只实现
Valuer而没有Scanner时,GORM不会把你的Date类型视为“可与数据库交互的自定义类型”,而是当作普通的结构体处理。这时候写入数据时,GORM不会调用你实现的Value()方法,而是直接处理结构体内部的time.Time字段——但因为类型识别失败,最终数据库接收到的是空值。 - 当你实现
Scanner接口后,GORM确认这个类型具备完整的数据库双向转换能力,才会在写入流程中正确调用Value()方法,把格式化后的日期字符串存入数据库,所以查询出来的start_date也是正常的。
哪怕你暂时不需要从数据库读取数据的功能,GORM的类型校验逻辑还是要求自定义类型同时实现这两个接口,这样它才能完成正确的类型映射和值绑定。
内容的提问来源于stack exchange,提问作者Noobie
相关产品推荐
相关产品推荐

