go-mysql,一個易用的mysql接口框架實現

介紹

go-mysql是一個用go寫的mysql driver,使用接口類似於go自身的database sql,但是稍微有一點不同,現階段還不支持集成進go database/sql中,但實現難度並不大,後續可能會接入。

go-mysql最先開始於mixer(一個用go實現的mysql proxy)中,隨着mixer的演化,我覺得有必要將其mysql模塊獨立出來使用。對於mixer,後續我會詳細介紹。

爲什麼要自己實現一套新的接口,而不是go自身的sql接口呢?最主要的原因在於我很不習慣使用Query的查詢方式。go自身的query例子:

age := 27
rows, 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)
}

可以看到,使用起來非常的繁瑣複雜,如果代碼裏面select語句很多(恰恰我們代碼裏面n多select),那麼如果每次select都要靠這種方式得到我們需要的結果,那我可能寫代碼會寫崩潰的。所以勢必我們需要提供一套封裝用來簡化select的結果集獲取。

Resultset

go-mysql跟go自身的sql接口最大的不一樣在於Query的時候直接返回了一個resultset,而這個resultset定義如下:

type Field struct {
    Name []byte
    Type uint8
    Flag uint16
}

type Resultset struct {
    Status uint16 //server status for this query resultset

    Fields     []Field
    FieldNames map[string]int

    Data [][]interface{}
}

Field用來表示查詢的時候返回的數據每列的名字,數據類型以及一些特定的Flag。而resultset中的Data則是存放了query結果中對於的實際數據。因爲對於mysql select來說,它返回的是一個"m x n"的結果集,我們直接使用[][]interface{}在go中表示。

Resultset提供了非常方便的接口用於select數據的獲取:

//指定某一行,某一列獲取數據,結果爲string
func (r *Resultset) GetString(row, column int) (string, error)
//執行某一行,某一列的名字獲取數據,結果爲string
func (r *Resultset) GetStringByName(row int, columnName int) (string, error)

接口

go-mysql除了query之外,幾乎提供了與go database/sql一樣的接口使用方式:

//創建一個db,最大允許保活16個空閒連接
//dsn格式爲:<username>:<password>@<host>:<port>/<database>
db := NewDB("qing:[email protected]:3306/mixer", 16)

//ping一下,看mysql server是不是還是活的
db.Ping()

//執行exec,包括insert,update,delete,replace
r, err := db.Exec("insert into mixer_conn (id, str) values (1, `abc`)")
println(r.LastInsertId(), r.RowsAffected())

//執行exec,語句中包含 ?佔位符,需要傳遞相應的參數
r, err := db.Exec("insert into mixer_conn (id, str) values (?, ?)", 2, "efg")
println(r.LastInsertId(), r.RowsAffected())

//執行select,得到結果集,並獲取相關數據
r, err := db.Query("select str from mixer_conn where id     = 1")
str, _ = r.GetString(0, 0)
str, _ = r.GetStringByName(0, "str")

//開始一個事物
tx, err = db.Begin()

//在事物裏面執行語句
tx.Exec("insert into mixer_conn (id, str) values (3, `abc`)")

//提交事物
tx.Commit()

//創建一個prepare statement
s, err := db.Prepare("insert into mixer_conn (id, str) values(?, ?)")

//執行 prepare statement
s.Exec(5, "abc")

//關閉 prepare statement
s.Close()

不光如此,go-mysql還提供單獨獲取一個conn,用於給外部額外使用的功能,譬如:

conn, err := db.GetConn()

//我需要設置conn的字符集爲gb2312
conn.SetCharset("gb2312")    

conn.Close()

可以看到,go-mysql的使用非常簡單,現階段正逐漸在我們項目中使用,也非常期待您的反饋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章