Edited at

[Go言語] database/sqlパッケージを使ってみた

More than 1 year has passed since last update.


ドライバを入れる

MySQLのドライバをいれてみる。

go get "github.com/go-sql-driver/mysql"

使うときは、init関数を呼び出せばよいみたいなので、_でインポートする。

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


データベースを開く

ドライバの名前を指定して、データベースに接続する。

cnn := sql.Open("mysql", "user:password@tcp(host:port)/dbname")


1レコードをSELECTしてみる

QueryRowメソッドを使えば、1レコード分を取得できる。

Go言語得意のポイントを渡して、出力引数で受け取る。

id := 100

var name string

if err := cnn.QueryRow("SELECT name FROM person WHERE id = ?LIMIT 1", id).Scan(&name); err != nil {
log.Fatal(err)
}

fmt.Println(id, name)


複数レコードをSELECTしてみる

Queryメソッドを使えば、複数のレコードを取得できる。

rows, err := cnn.Query("SELECT id, name FROM person")

if err != nil {
log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}

if err := rows.Err(); err != nil {
log.Fatal(err)
}


UPDATEしてみる

レコードを取得する必要のない、クエリはExecメソッドを使う。

result, err := cnn.Exec("UPDATE person SET name = ? WHERE id = ?", "Hogera", 100)

if err != nil {
log.Fatal(err)
}

Resultインタフェースを使うと、最後に挿入したレコードのキーや影響の合ったレコード数を取得できる。

type Result interface {

LastInsertId() (int64, error)
RowsAffected() (int64, error)
}


トランザクションを使ってみる


トランザクションの開始とコミット

Beginメソッドを呼び出すと、Tx型のポインタとエラー値が返ってくる。

Tx型はDB型と似たようなメソッドを持っているため、QueryQueryRowExecなどが使える。

tx, err := cnn.Begin()

if err != nil {
log.Fatal(err)
}

Commitメソッドを使えばコミットできる。

tx.Commit()


ロールバック

Rollbackメソッドでロールバックできる。

以下の例は、パニックが起きたら、ロールバックする例である。

func hoge(tx *sql.Tx) {

defer func() {
// panicがおきたらロールバック
if err := recover(); err != nil {
tx.Rollback()
}
}()
// …
tx.Exec(…)
}


感想

ドキュメントを見ると、コネクションプールとかよしなにやってくれるらしい。

最初は以下のようにやってたけど、不要のようだ。

var cnnPool chan *sql.DB

func main() {
cnnPool = make(chan *sql.DB, 10)
for i := 0; i < cap(cnnPool); i++ {
cnnPool <- sql.Open("mysql", "user:password@tpc(host:port)/dbname")
}
}

func getFromDB() {
cnn := <-cnnPool
defer func() {
cnnPool <- cnn
}()
// cnnを使った処理
}

まだまだ、使い始めたばっかなので、基本的な使い方だけまとめた。