go语言scan空值报错
leonpengweicn · · 8284 次点击 · · 开始浏览http://xmarker.blog.163.com/blog/static/22648405720144743531420/
今天使用go语言时,如果数据库里有空值,扫描出来报错,其中环境是这样的,数据库为postgresql9.3.2(其实和数据库无关),数据库里的数据如下:
import(
"fmt"
"time"
"zypublic/zyutil/zydbhelp"
)
funcmain(){
conn,err:=zydbhelp.ConnDBByService("public",true)
iferr!=nil{
fmt.Println(err)
}
stmt,err:=conn.Prepare("selectid,name,remark,time,agefromt_tmp")
iferr!=nil{
fmt.Println(err)
}
varvidint64
varvnamestring
varvremarkstring
varvtimetime.Time
varvagefloat64
rows,err:=stmt.Query()
iferr!=nil{
fmt.Println(err)
}
forrows.Next(){
err=rows.Scan(&vid,&vname,&vremark,&vtime,&vage)
iferr!=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
varvnamestring
varvremarksql.NullString
varvtimetime.Time
varvagesql.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)iferr!=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的结果!
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
http://xmarker.blog.163.com/blog/static/22648405720144743531420/
今天使用go语言时,如果数据库里有空值,扫描出来报错,其中环境是这样的,数据库为postgresql9.3.2(其实和数据库无关),数据库里的数据如下:
import(
"fmt"
"time"
"zypublic/zyutil/zydbhelp"
)
funcmain(){
conn,err:=zydbhelp.ConnDBByService("public",true)
iferr!=nil{
fmt.Println(err)
}
stmt,err:=conn.Prepare("selectid,name,remark,time,agefromt_tmp")
iferr!=nil{
fmt.Println(err)
}
varvidint64
varvnamestring
varvremarkstring
varvtimetime.Time
varvagefloat64
rows,err:=stmt.Query()
iferr!=nil{
fmt.Println(err)
}
forrows.Next(){
err=rows.Scan(&vid,&vname,&vremark,&vtime,&vage)
iferr!=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
varvnamestring
varvremarksql.NullString
varvtimetime.Time
varvagesql.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)iferr!=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的结果!