Go与PostgreSQL单元测试插入整数时出现nil转int64扫描错误
解决Go单元测试中
sql: Scan error on column index 0的问题 看起来你遇到的问题有点反直觉——明明给testDevice的ID设成了整数1,插入后却触发了nil转int64的Scan错误。我来帮你拆解下可能的原因和解决办法:
核心问题分析
这个错误本质是:数据库返回的第一条列(也就是你的ID列)值为nil,但你的结构体ID字段是int64类型,无法接收nil值。哪怕你手动设置了ID=1,也可能被数据库的规则覆盖,导致返回值异常。
排查&解决步骤
1. 先检查Device结构体的DB标签配置
大概率是结构体的字段映射出了问题,尤其是ID字段的标签。假设你用的是sqlx的Dbmap,正确的结构体定义应该类似这样:
type Device struct { ID int64 `db:"id,primarykey,autoincr"` // 重点:标签要匹配表字段,自增主键需加autoincr Guid string `db:"guid"` Name string `db:"name"` }
- 如果你的
ID字段没有加db标签,或者标签名和数据库表字段不匹配,Dbmap无法正确映射数据库返回的ID值; - 如果
ID是自增主键,必须加上autoincr标签,这样Dbmap才会自动把数据库生成的ID填充回结构体。
2. 确认数据库表结构是否合理
检查你的devices表(假设表名是这个)的id字段配置:
- 如果是自增主键,必须设置为
AUTO_INCREMENT(MySQL)或SERIAL(PostgreSQL),且不能允许NULL; - 如果不是自增主键,要确保字段不允许
NULL,且插入时手动设置的ID=1能被数据库正常接收(比如没有主键冲突、触发器修改ID等情况)。
举个MySQL的正确表结构示例:
CREATE TABLE devices ( id INT AUTO_INCREMENT PRIMARY KEY, guid VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL );
3. 调整插入逻辑,匹配自增规则
如果ID是自增主键,不要手动设置ID值——数据库会自动生成,Dbmap会把生成的ID填充回你的结构体:
func Test1(t *testing.T){ //Code testDevice := Device{ Guid: "C6", Name: "test device", } // 去掉手动设置的ID err := Dbmap.Insert(&testDevice) So(err, ShouldBeNil) // 此时testDevice.ID已经被填充为数据库生成的自增ID //More code }
如果你强行手动设置自增ID,部分数据库会忽略你的值,返回自己生成的ID;如果结构体标签没配置好,就会出现nil转int64的错误。
4. 开启SQL日志定位细节
如果以上步骤都没解决问题,建议开启Dbmap的SQL日志,查看实际执行的SQL和返回结果:
import "log" import "os" func init() { // 在测试初始化时开启SQL追踪 Dbmap.TraceOn("", log.New(os.Stdout, "SQL: ", log.Lmicroseconds)) }
这样你能清楚看到插入语句的实际执行情况,以及数据库返回的字段值,更容易定位到底是哪一步出了问题。
内容的提问来源于stack exchange,提问作者Errorum
相关产品推荐
相关产品推荐

