PostgreSQLにアクセスする
標準ライブラリであるdatabase/sql
を利用してPostgreSQLにアクセスしてみます。
データベースドライバのインストール
SQLDrivers にドライバの一覧があります。
PostgreSQLのドライバがいくつかありますが今回はlib/pq
を利用します。
$ go get github.com/lib/pq
データベースへの接続
sql.Open()
でデータベースオブジェクトを生成します。この関数は*sql.DB
を返します。
db, err := sql.Open("postgres", "host=localhost port=32768 user=postgres dbname=golang_dev sslmode=disable")
sql.Open()
はドライバや接続文字列のバリデーションをしているだけで実際は接続しません。
db.Ping()
したりクエリを発行した時点でコネクションが確立します。
クエリの発行
参照系は複数件取得するdb.Query()
、1件取得するdb.QueryRow()
を利用します。
rows, err := db.Query("select id, name from users where id = $1", 1) for rows.Next() { err := rows.Scan(&id, &name) }
rows.Scan()
は渡した変数の型に応じてタイプキャストしてくれます。
例えばidはデータベース上bigint
で定義していますが変数id string
を渡せば文字列型で取得できます。(あまりよろしくないと思いますが)
キャストできない型は当然エラーになります。
sql: Scan error on column index 1: converting driver.Value type string ("foo") to a int: invalid syntax
更新系はdb.Exec()
を利用します。
db.Exec("insert into users (name) values ($1)", "foo")
プリペアドステートメントを使えるdb.Prepare()
とかもあります。
関数化とかしてませんがまとめるとこんな感じ。
package main import ( "database/sql" _ "github.com/lib/pq" "log" ) func main() { // DBオブジェクト生成 db, err := sql.Open("postgres", "host=localhost port=32768 user=postgres dbname=golang_dev sslmode=disable") if err != nil { log.Fatal(err) } defer db.Close() // 疎通確認 err = db.Ping() if err != nil { log.Fatal(err) } // 登録 stmt, err := db.Prepare("insert into users (name) values ($1)") if err != nil { log.Fatal(err) } res, err := stmt.Exec("Foo") if err != nil { log.Fatal(err) } rowCnt, err := res.RowsAffected() if err != nil { log.Fatal(err) } log.Printf("affected = %d\n", rowCnt) // 取得 var ( id int name string ) rows, err := db.Query("select id, name from users") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } err = rows.Err() if err != nil { log.Fatal(err) } }