分享
  1. 首页
  2. 文章

go语言scan空值报错

leonpengweicn · · 8284 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

http://xmarker.blog.163.com/blog/static/22648405720144743531420/


今天使用go语言时,如果数据库里有空值,扫描出来报错,其中环境是这样的,数据库为postgresql9.3.2(其实和数据库无关),数据库里的数据如下:

db_public=> \d t_tmp
Table "usr_public.t_tmp"
Column | Type | Modifiers
--------+-----------------------------+-----------
id | integer | not null
name | character varying(30) |
remark | text |
time | timestamp without time zone |
age | numeric(18,4) |
Indexes:
"t_tmp_pkey" PRIMARY KEY, btree (id)

db_public=> select * from t_tmp;
id | name | remark | time | age
----+--------+-------------+----------------------------+---------
1 | zyj071 | insert test | 2014年04月02日 17:17:21.176196 |
2 | 马到成功 | | 2014年05月07日 15:23:27.479841 |
3 | 众人 | 测试 | 2014年05月07日 15:38:14.135305 | 17.2340
(3 rows)

go代码如下:
packagemain

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


经过一番google后发现,go语言有自带的sql.NullFloat类型可供我们使用,于是用sql.NullFloat64来代替Float64,代码如下:

varvidint64
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的结果!



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:leonpengweicn

查看原文:go语言scan空值报错

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
8284 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏