iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
0

再來我們來介紹,如果要做 web 相關應用服務,免不了一定有 database 相關需求,我們就以 mysql 當做例子,作為今天主題

mysql

golang 其實在 database 的存取上,他設計了一個 sql 抽象介面叫做 database/sql,接下來只要有不同人的遵照這個 interface 分開去實作 mysql、sqlite ... 等等,這是一個很棒的設計,如果未來你有測試或是抽換需求,其實只要更新 driver ,但完全不需要更動你的程式相關地方

在這邊簡單介紹一下 golang mysql driver ,最知名的應該是這套 go-sql-driver/mysql

先從連線做起

import "database/sql"
import _ "github.com/go-sql-driver/mysql"


//完整的資料格式連線如下
//[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
db, err := sql.Open("mysql", "user:password@/dbname")

再來如果要執行寫入

result, err := db.Exec(
    "INSERT INTO user_info (name, age) VALUES (?, ?)",
    "syhlion",
    18,
)

執行查詢(單筆)

var age int
row := db.QueryRow("SELECT age FROM user_info WHERE name = ?","syhlion")
err := row.Scan(&age)

執行查詢(多筆)

rows, err := db.Query("SELECT name FROM user_info WHERE age > ?", 16)
if err != nil {
    log.Fatal(err)
}

//切記用完都要做 Close
defer rows.Close()
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)
}

如果要 transcation

tx, err := db.Begin()
if err != nil {
    return
}
defer func(){

    //如果最後有錯誤,則執行 rollback
    if err != nil {
        tx.RollBack()
    }
}

...
...
...


tx.Commit()

在這邊我提供了一個,我自己二度包裝過的套件 syhlion/sqlwrapper,基本上都跟上面所提供的方法或使用方式一模一樣,只是我稍微包裝過有添加了一些 log、監控、debug... 相關功能<
,用法如下

func main(){
    db, err := sql.Open("xxx","xxx")
    if err != nil {
        return nil, err
    }

    //這邊第二參數為是否開啟 debug 模式,如為 true 則強制開啟 sql log模式
    //第三個參數為如果sql 執行速度慢於多少時間,則會印出該筆 sql 的 log
    db := WrapperDB(db,true,1*time.Second)


    // it log [sql] select * from member where id = ?  1  2s
    rs,err:=db.Exec("select * from member where id = ?",1)
    if err != nil {
        return
    }

}

印出的 log 樣子如下

{
  "args": [
    "syhlion",
    18
  ],
  "ip": "172.18.0.12",
  "level": "debug",
  "msg": "db query",
  "name": "syhlion/sqlwrapper",
  "sql": "SELECT * FROM user_info WHERE name = ? AND age = ?",
  "time": "2018-11-01T16:55:00+08:00",
  "use-time": "5.7768ms"
}

會有這樣的包裝的理念是因為,方便工程師在開發期時 debug ,確認自己的 sql 有正確執行、也方便上線後監控每句 sql 的執行速度。


上一篇
Golang 如何使用 grpc
下一篇
Golang 如何使用 redis
系列文
Go劍復國-30天導入Golang30

尚未有邦友留言

立即登入留言