LoginSignup
220
184

More than 5 years have passed since last update.

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

Last updated at Posted at 2013-10-02

ドライバを入れる

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を使った処理
}

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

220
184
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
220
184