【轉載】記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()執行起來報錯
- sql: Scan error on column index 0: unsupported driver -> Scan pair: time.Time -> *sql.RawBytes
複製程式碼
OK,抽了根去,將datetime轉換層char,於是
- returndata := openDbString("select top 1 CONVERT(CHAR(23), createtime, 121) as createtime from ATRes ")
- fmt.Println("result:", returndata)
返回結果如下
- {"timestamp": "2015-06-11 11:51:22","data":[{"createtime":"2015-05-06 1"}]}
結果是時間被截斷了,再次嘗試
- returndata := openDbString("select top 1 CONVERT(CHAR(36), createtime, 121) as createtime from ATRes ")
- fmt.Println("result:", returndata)
複製程式碼
返回結果如下,這次OK
- {"timestamp": "2015-06-11 11:53:53","data":[{"createtime":"2015-05-06 16:15:42"}]}
複製程式碼
2.長文字被截斷的坑
- returndata := openDbString("select top 1 data from ATRes ")
- fmt.Println("result:", returndata)
返回結果如下
- {"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 再次修改查詢語句驗證猜想
- returndata := openDbString("select top 1 cast(data as CHAR(200)) as datacopy,data from ATRes ")
- fmt.Println("result:", returndata)
複製程式碼
返回結果如下
- {"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裡面,這不科學 於是我又倒騰了一把
- returndata := openDbString("select top 1 rtrim(cast(data as CHAR(200))) as datacopy,data from ATRes ")
- fmt.Println("result:", returndata)
返回結果如下,終於OK了
- {"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實在是太方便了 又臭又長的原始碼就不上傳了