my golib:db query Result

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

go提供了一套統一操作database的sql介面,任何第三方都可以通過實現相應的driver來訪問感興趣的資料庫。譬如我們項目中使用的Go-MySQL-Driver。

go提供了一套很好的機制來處理資料庫的查詢操作,譬如官方的例子:

age := 27rows, err := db.Query("SELECT name FROM users WHERE age=?", age)if err != nil {        log.Fatal(err)}for rows.Next() {        var name string        if err := rows.Scan(&name); err != nil {                log.Fatal(err)        }        fmt.Printf("%s is %d\n", name, age)}if err := rows.Err(); err != nil {        log.Fatal(err)}

在上面的例子中,Query會返回一個rows,我們通過Next擷取下一行資料,然後使用Scan將每行的資料設定到相應的變數上面去。

雖然這樣操作查詢結果集很方便,但是我們在使用過程中,發現當sql query語句過多,如果每一個查詢都按照這種寫法,代碼量太大了。所以,我們自然就想到了封裝。

db result主要進行的工作就是提供一套統一的介面供外部方便的使用查詢的結果集,它主要提供了如下幾個介面:

func (*Result) GetInt(row, col int) (int64, error)func (*Result) GetIntByName(row int, colName string) (int64, error)func (*Result) GetFloat(row, col int) (float64, error)func (*Result) GetFloatByName(row int, colName string) (float64, error)func (*Result) GetBool(row, col int) (bool, error)func (*Result) GetBoolByName(row int, colName string) (bool, error)func (*Result) GetString(row, col int) (string, error)func (*Result) GetStringByName(row int, colName string) (string, error)func (*Result) GetBuffer(row, col int) ([]byte, error)func (*Result) GetBufferByName(row int, colName string) ([]byte, error)

可以看到,result的“Get*”介面通過結果集的row和col的索引來訪問資料,而"Get*ByName"介面則是通過row以及col的名字來訪問資料。

因為go支援很多的資料類型,為了簡單起見,所有int類型的我們統一使用int64代替,外部在進行相應的資料轉換。同理float類型也是用float64代替。如果查詢的結果某個欄位為空白,result只是返回該欄位預設的數值。通常情況下,我都會要求資料庫中的欄位都為not null,所以查詢欄位為null的情況這裡沒有過多考慮。

一個很簡單的例子:

//msg_id bigint//msg varchar(256)res, err := Query("is", "select msg_id, msg from msg_table where msg_id in (?, ?)", 1, 2)var id1 int64id1, err = res.GetInt(0, 0)var msg2 stringmsg2, err = res.GetStringByName(1, "msg")

在上面的例子中,我們在查詢的時候返回了一個result,然後通過相關的函數擷取到了相應的資訊。這裡我們需要特別注意的就是Query後面的第一個參數“is”

在Go-MySQL-Driver中,會兩種結果集模式,一個是text rows,另一個則是binary rows(使用stmt query的結果集),在text rows中,所有的資料都是[]byte格式,而在binary rows中,則會根據stmt對應的結果類型轉換成相應的資料。為了統一,我們通過在query的時候手動指定column types,在row scan的時候直接建立對應的類型資料,供scan設定。如下:

func (res *Result) newValue(column int) (interface{}, error) {    t := res.ColumnTypes[column]    switch t {    case Column_String:        return new(string), nil    case Column_Int:        return new(int64), nil    case Column_Bool:        return new(bool), nil    case Column_Float:        return new(float64), nil    case Column_Buffer:        return new([]byte), nil    default:        return nil, ErrColumnTypes    }}//遍曆結果集的時候,我們根據column types產生指定的value,並通過Scan設定for rows.Next() {    dest := make([]interface{}, len(res.ColumnNames))    for i, _ := range dest {        dest[i], err = res.newValue(i)        if err != nil {            return err        }    }    err = rows.Scan(dest...)    if err != nil {        return err    }

如果大家使用過mysql_stmt_bind_result,就可以發現,column types的概念其實就跟設定MYSQL_BIND差不多,只是result為了簡單,只支援int64,float64,bool,string,以及[]byte這幾種類型。

具體的代碼在這裡https://github.com/siddontang/qpush/blob/master/go/src/lib/db/result.go。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.