[Go言語] database/sqlパッケージを使ってみた
October 2, 2013
この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。
ドライバを入れる
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
型と似たようなメソッドを持っているため、Query
やQueryRow
、Exec
などが使える。
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を使った処理
}
まだまだ、使い始めたばっかなので、基本的な使い方だけまとめた。