1. 程式人生 > 其它 >【轉載】記Golang資料庫查詢封裝的坑

【轉載】記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實在是太方便了 又臭又長的原始碼就不上傳了