Go标准库database/sql,Rows.Scan NULL问题

saxon134 · 2020-05-21 17:56:56 · 3877 次点击 · 预计阅读时间 1 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2020-05-21 17:56:56 的文章,其中的信息可能已经有所发展或是发生改变。

使用Go标准库database/sql,Rows.Scan如果遇到NULL,则会报错,并且停止Scan后续的字段,导致获得的数据不完整。

比如:

type TblUser struct {
   Id        int64
   LastIp     string
   NickName   string    
   Avatar     string    
   Lang       string    
}

假设LastIp为NULL,其他字段都有数据,但是Rows.Scan的时候,只能识别出Id,其他字段都无法正确读出。

而NULL在数据库又很容易遇到,摸索了一段时间,找到一个方案,先上代码:

m := new(TblUser)
dest := []interface{}{&(m.Id), &(m.LastIp), &(m.NickName), &(m.Avatar)}
newDest := make([]interface{}, 0, len(dest))
empty := sql.NullBool{}

queryValue := reflect.Indirect(reflect.ValueOf(query))
queryValue = queryValue.FieldByName("lastcols")
cnt := queryValue.Len()
for i := 0; i < cnt; i++ {
   v := queryValue.Index(i)
   v_ok := false
   if v.IsValid() {
      if v.InterfaceData()[0] != 0 {
         newDest = append(newDest, dest[i])
         v_ok = true
      }
   }
   if v_ok == false {
      newDest = append(newDest, &empty)
   }
}

_ = query.Scan(newDest...)

思路是:

  1. 通过反射,拿得从数据库获得的数据,即:lastcols

    lastcols是在结构体的非公开变量,所以需要反射

  2. 遍历lastcols,获取每项的interfaceData(),判断是否有数据

  3. 如果没有数据,则将scan结果放到一个sql.NullBool{}变量,该类型由引擎提供,可以接受NULL

  4. 最后就可以正常scan了


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

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

3877 次点击  ∙  1 赞  
加入收藏 微博
3 回复  |  直到 2021-02-06 09:44:30
Schr0dingerCat
Schr0dingerCat · #1 · 5年之前

这个方法有点不太方便,我是直接在查询的时候,用了ISNULL()来把数据库中的null给去了

jarlyyn
jarlyyn · #2 · 5年之前

…………

直接将lastip类型设置为*string就好了……

zh23jemu
zh23jemu · #3 · 4年之前

其实直接用sql.NullString这个类型就能处理了

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