http://xmarker.blog.163.com/blog/static/22648405720144743531420/
今天使用go语言时,如果数据库里有空值,扫描出来报错,其中环境是这样的,数据库为postgresql9.3.2(其实和数据库无关),数据库里的数据如下:
import (
"fmt"
"time"
"zypublic/zyutil/zydbhelp"
)
func main() {
conn, err := zydbhelp.ConnDBByService("public", true)
if err != nil {
fmt.Println(err)
}
stmt, err := conn.Prepare("select id,name,remark,time,age from t_tmp")
if err != nil {
fmt.Println(err)
}
var vid int64
var vname string
var vremark string
var vtime time.Time
var vage float64
rows, err := stmt.Query()
if err != nil {
fmt.Println(err)
}
for rows.Next() {
err = rows.Scan(&vid, &vname, &vremark, &vtime, &vage)
if err != nil {
fmt.Println("scan报错:", err)
}
fmt.Println("result是:", vid, "<==>", vname, "<==>", vremark, "<==>", vtime, "<==>", vage)
}
}
执行结果如下:
scan报错: sql: Scan error on column index 4: converting string "<nil>" to a float64: strconv.ParseFloat: parsing "<nil>": invalid syntax
result是: 1 <==> zyj071 <==> insert test <==> 2014-04-02 17:17:21.176196 +0000 UTC <==> 0
scan报错: sql: Scan error on column index 2: unsupported driver -> Scan pair: <nil> -> *string
result是: 2 <==> 马到成功<==> insert test <==> 2014-04-02 17:17:21.176196 +0000 UTC <==> 0
result是: 3 <==> 众人 <==> 测试 <==> 2014-05-07 15:38:14.135305 +0000 UTC <==> 17.234
var vname string
var vremark sql.NullString
var vtime time.Time
var vage sql.NullFloat64
然后再编译运行,结果如下:
result是: 1 <==> zyj071 <==> {insert test true} <==> 2014-04-02 17:17:21.176196 +0000 UTC <==> {0 false}
result是: 2 <==> 马到成功 <==> { false} <==> 2014-05-07 15:23:27.479841 +0000 UTC <==> {0 false}
result是: 3 <==> 众人 <==> {测试 true} <==> 2014-05-07 15:38:14.135305 +0000 UTC <==> {17.234 true}
可以看到vremark和vage都是struct类型来,经过查看godoc,sql.Null类型的为struct结构体:
type NullFloat64 struct { Float64 float64 Valid bool // Valid is true if Float64 is not NULL }后续处理可以判断vage.Valid是否为true写个if else进行处理。
本来以为到这就结束了,但之前我不经意间查询都是没问题的,为啥这次有问题呢,仔细核对代码,发现这部分有问题:
err = rows.Scan(&vid, &vname, &vremark, &vtime, &vage)
if err != nil {
fmt.Println("scan报错:", err)
}
如果不用err接收rows.Scan的结果,数据都是可以正常输出的:
rows.Scan(&vid, &vname, &vremark, &vtime, &vage)
这样显示如下:
result是: 1 <==> zyj071 <==> insert test <==> 2014-04-02 17:17:21.176196 +0000 UTC <==> 0
result是: 2 <==> 马到成功 <==> insert test <==> 2014-04-02 17:17:21.176196 +0000 UTC <==> 0
result是: 3 <==> 众人 <==> 测试 <==> 2014-05-07 15:38:14.135305 +0000 UTC <==> 17.234
这样不需要使用sql.Null***类型,用原始类型就可以处理了,但这样的话null会显示成0或空字符串,而且第二行马到成功后面在数据库是空值,但查询出来竟然也是insert test,使用的是上一行的值,因此一定不能忘记用err接收rows.Scan的结果!
有疑问加站长微信联系(非本文作者)