Go标准库database/sql中Rows.Err()工作机制及异常问题咨询
Rows.Err()的预期工作逻辑
Rows.Err()的设计目标是捕获迭代过程中数据库驱动/底层IO层面产生的用户不可控错误,仅包含以下几类错误:
rows.Next()执行时遇到的数据库连接中断、结果集传输错误、底层协议解析错误- 迭代未读完所有行就终止时,剩余行数据传输过程中产生的错误
- 显式/隐式调用
Close()释放资源时产生的底层错误
官方给出的方法说明如下:
Err返回迭代过程中遇到的错误,可在显式或隐式调用Close后调用。
你的理解偏差
你错误地认为Scan()返回的所有错误都会被Rows.Err()捕获,实际上这两类错误的产生场景完全不同:Scan()返回的错误分为两类:
- 底层读取行数据产生的错误:这类错误会被同步写入Rows的err字段,可以通过
Rows.Err()获取 - 用户使用层面的校验错误:比如参数数量不匹配、类型转换失败这类由
Scan()方法主动校验返回的错误,不属于底层迭代错误范畴,不会被记录到Rows的err字段中,自然无法通过Rows.Err()获取。你测试时触发的sql: expected 6 destination arguments in Scan, not 5就属于这类错误。
标准错误处理写法
实际开发中需要同时处理Scan()返回的使用错误和Rows.Err()返回的底层错误:
var err error for rows.Next() { t := someStruct{} err = rows.Scan(&t.Field1, &t.Field2, &t.Field3, &t.Field4, &t.Field5, &t.Field6) if err != nil { // 优先处理Scan层面的错误 log.Debug(err) break } templates = append(templates, &t) } // 显式关闭结果集 rows.Close() // 再判断底层迭代错误 if rowsErr := rows.Err(); rowsErr != nil { log.Error(rowsErr) }
内容的提问来源于stack exchange,提问作者Aditya Kumar Gupta
相关产品推荐
相关产品推荐

