【转载】记Golang数据库查询封装的坑

前文 golang接触也有一段时间,项目中有用到web api,基本上就是post json格式的,本想用java来写,刚下手想到java太臃肿,各种繁琐。觉得用golang小试一把,于是github一把,还是发现很多go rest 插件,选了一个https://github.com/ant0ine/go-json-rest一根烟后,go-json-rest demo开始跑起来,使用curl命令模拟了一把,正确运行。关于go-json-rest的使用,本文不做描述,官方文档有很详细的说明https://github.com/ant0ine/go-json-rest 正文 这是封装数据库的连接的核心代码(其实大部分是网上copy的)此方法是将sql的查询结果封装成json格式输出(当然是方便post返回值)

func openDbString(sqlstring string) string {
    conn := openDb()
    defer conn.Close()
    stmt, err := conn.Prepare(sqlstring)
    if err != nil {
        fmt.Println("Query Error", err)
        return "Error"
    }
    defer stmt.Close()
    rows, err := stmt.Query()
    if err != nil {
        fmt.Println("Query Error", err)
        return "Error"
    }
    defer rows.Close()
    // Get column names
    columns, err := rows.Columns()
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
    // Make a slice for the values
    values := make([]sql.RawBytes, len(columns))
    // rows.Scan wants '[]interface{}' as an argument, so we must copy the
    // references into such a slice
    // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details
    scanArgs := make([]interface{}, len(values))
    for i := range values {
        scanArgs[i] = &values[i]
    }
    // Fetch rows
    var jsonstring string
    jsonstring = "{\"timestamp\": \"" + time.Now().Format("2006-01-02 15:04:05") + "\",\"data\":["
    allcount := 0
    for rows.Next() {
        jsonstring += "{"
        // get RawBytes from data
        err = rows.Scan(scanArgs...)
        if err != nil {
            panic(err.Error()) // proper error handling instead of panic in your app
        }
        // Now do something with the data.
        // Here we just print each column as a string.
        var value string
        for i, col := range values {
            // Here we can check if the value is nil (NULL value)
            if col == nil {
                value = "NULL"
            } else {
                value = string(col)
            }
            //          fmt.Println(columns[i], ": ", value)
            if i == len(values)-1 {
                jsonstring += "\"" + columns[i] + "\":\"" + value + "\""
            } else {
                jsonstring += "\"" + columns[i] + "\":\"" + value + "\","
            }
            //          fmt.Println(" :", i, ": ", col, len(values))
        }
        //fmt.Println("replace before :", jsonstring, ": ", len(jsonstring))
        //jsonstring = strings.Replace(jsonstring, ",", " ", len(jsonstring))
        //fmt.Println("replace after :", jsonstring, ": ", len(jsonstring))
        //      fmt.Println("-----------------------------------", allcount)
        jsonstring += "},"
        allcount++
    }
    if allcount > 0 {
        jsonstring = Substr(jsonstring, 0, len(jsonstring)-1)
    }
    jsonstring += "]}"
    if err = rows.Err(); err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
    return jsonstring
}

接下来来记录sql查询结果的坑

网上的有很多golang查询数据库的栗子,但是都是简单的使用 而我却被坑了好几次,细述如下

1.时间函数的坑

由于在sql字段定义的datetime,直接使用getdate()运行起来报错

  1. sql: Scan error on column index 0: unsupported driver -> Scan pair: time.Time -> *sql.RawBytes

复制代码

OK,抽了根去,将datetime转换层char,于是

  1. returndata := openDbString("select top 1 CONVERT(CHAR(23), createtime, 121) as createtime from ATRes ")
  2. fmt.Println("result:", returndata)

返回结果如下

  1. {"timestamp": "2015-06-11 11:51:22","data":[{"createtime":"2015-05-06 1"}]}

结果是时间被截断了,再次尝试

  1. returndata := openDbString("select top 1 CONVERT(CHAR(36), createtime, 121) as createtime from ATRes ")
  2. fmt.Println("result:", returndata)

复制代码

返回结果如下,这次OK

  1. {"timestamp": "2015-06-11 11:53:53","data":[{"createtime":"2015-05-06 16:15:42"}]}

复制代码

2.长文本被截断的坑

  1. returndata := openDbString("select top 1 data from ATRes ")
  2. fmt.Println("result:", returndata)

返回结果如下

  1. {"timestamp": "2015-06-11 11:57:10","data":[{"data":"http://jixieshi999.github.io/ilife/images/mamabeat."}]}

实际上data字段在数据库里面是一个图片的url,但是输出结果里面,url被截断了(.jpg丢失了) 猜测下,可能是sql数据类型和golang的读取数据类型不一致导致的,由于sql里面data是nvacher(100)的类型,而输出的是截断的长度,哥哥我果断数了一下data的长度,刚好是50,so 50=?100/2 再次修改查询语句验证猜想

  1. returndata := openDbString("select top 1 cast(data as CHAR(200)) as datacopy,data from ATRes ")
  2. fmt.Println("result:", returndata)

复制代码

返回结果如下

  1. {"timestamp": "2015-06-11 12:01:54","data":[{"datacopy":"http://jixieshi999.github.io/ilife/images/mamabeat.jpg。。。。。。。。。。。。。。。","data":"http://jixieshi999.github.io/ilife/images/mamabeat."}]}

注意,datacopy后面的若干空格我用。代替方便查看,这种结果还是不满足我的胃口,不可能有这么多空格在json里面,这不科学 于是我又倒腾了一把

  1. returndata := openDbString("select top 1 rtrim(cast(data as CHAR(200))) as datacopy,data from ATRes ")
  2. fmt.Println("result:", returndata)

返回结果如下,终于OK了

  1. {"timestamp": "2015-06-11 12:05:22","data":[{"datacopy":"http://jixieshi999.github.io/ilife/images/mamabeat.jpg","data":"http://jixieshi999.github.io/ilife/images/mamabeat."}]}

关于golang获取当前时间的坑,百度下就有了 后记

总结下来golang对于数据库的支持还是没有java方便,也有本人对golang的了解不够深入的问题 不过用golang做前文说的restful api实在是太方便了 又臭又长的源代码就不上传了

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2016-01-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏更流畅、简洁的软件开发方式

见到了“公司”定义一个Company类,那么见到了“字段”是不是也可定义一个Column类?

  既然见到了公司,我们可以定义一个Class Company ,那么我们见到了字段,是不是也可以定义一个Class ColumnInfo呢? 公司的描述信息类...

2529
来自专栏web前端教室

[每周日-先行者课堂笔记] -- react版的倒计时实现

image.png 各位同学们大家好,今天是4月9号周日,今天我们继续来做“倒计时”这个前端组件。之前我们是使用原生js来实现的,其实更多的只是实现了功能。 这...

3517
来自专栏游戏杂谈

使用vbscript替换excel文件的内容

这个不能算瞎折腾,也算是被逼的没办法了。从接手webgame开始,看到那么多的excel文件被翻译为繁体,我的头就没小过。现在因为新版本的问题又得重新翻译一次...

2262
来自专栏张善友的专栏

Notepad2 一个很不错的记事本

有如下特性: 1、自定义语法高亮,支持HTML, XML, CSS, JavaScript, VBScript, ASP,PHP, CSS, Perl/CGI,...

2549
来自专栏架构师之旅

Oracle的常见问题汇总(1)——​Oracle中的JOIN的整理和结构分析

oracle中的join的整理和结构分析 在Oracle中的join主要分为: 外连接(outter join),内连接(inner join),自身连接(se...

2055
来自专栏黒之染开发日记

【easeljs】事件汇总

文章说明:为了方便我自己查找easeljs的所有事件,所以我从easeljs的文档里抄过来加上自己的翻译,会慢慢补全,漏了的,错了的,评论一下我会补上去哦。(不...

1322
来自专栏五毛程序员

thymeleaf-extras-db 0.0.1发布,select标签加载数据的新姿势

在写thymeleaf页面的时候,我为了偷懒,不想为每个select下拉列表框都写一个接口,于是这个懒人jar诞生了。该jar的核心功能是直接通过thymele...

1323
来自专栏GreenLeaves

C# 文件操作系列一

在.Net环境中,所有关于文件操作的类都在System.IO命名空间下,注:在修改文件时,安全性显得格外重要,但是本随笔不过多讲述安全性,这里假设我们有足够的权...

2585
来自专栏林德熙的博客

win10 uwp 绑定 OneWay 无法使用

有时候使用绑定的 OneWay 方法无法使用,而使用 TwoWay 的方法就可以使用,但是在调试把 OneWay 做了修改又可以使用,那么请看本文。

871
来自专栏landv

实现用VB.Net/(C#)开发K/3 BOS 插件的真正可行方法

1531

扫码关注云+社区

领取腾讯云代金券