2012/09/14

Recent entries from same category

  1. Golang で HTTP コンテンツの charset 判定をするには
  2. Golang の archive/zip でタイムゾーンの問題とファイル名の問題が解決した。
  3. Golang で優先度を変えてプロセスを起動する。
  4. net/http でレスポンスの内容を確認したいなら io.TeeReader を使おう
  5. Golang で物理ファイルの操作に path/filepath でなく path を使うと爆発します。

そろそろWeb周りだけでなくDB周りも揃ってきて、本格的なアプリケーションが書ける様になってきました。
DBを扱うには、SQLを実行する様な物は標準でサポートしていましたが、gorp を使うと極力SQLを書かずにデータベースを扱う事が出来ます。
coopernurse/gorp - GitHub

Go Relational Persistence I hesitate to call gorp an ORM.

https://github.com/coopernurse/gorp
まずエンティティとなる構造体を宣言します。ここでは Person という構造にします。
type Person struct {
    Id int32
    Name string
}
次に、データベースマッパーを作ります。
db, err := sql.Open("sqlite3""./foo.db")
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
ドライバはSQLite3を使いましたが、MySQLとPostgreSQLもサポートしている様です。 なお、gorp では使えませんが、Go言語で使えるデータベースは以下のWikiにエントリされています。
SQLDrivers - go-wiki - SQL database drivers - Go Language Community Wiki - Google Project Hosting

SQL database drivers The database/sql and database/sql/driver packages are designed for using databa...

http://code.google.com/p/go-wiki/wiki/SQLDrivers
手前味噌ですが、SQLite3 と Oracle(OCI8)、Microsoft ADODB のドライバは僕が作った奴です。バグあったら教えて下さい。

さて、データベースマッパーが出来たらテーブルと構造体の紐付けを行います。
t := dbmap.AddTableWithName(Person{}, "person").SetKeys(true"Id")
t.ColMap("Id").Rename("id")
t.ColMap("Name").Rename("name")
person というテーブル名で Person 構造体を登録し、Id がキーである事を教えています。その後、カラム名のリネームも行っています。テーブルのフィールド名先頭が大文字とか気持ち悪いとか、UserName というフィールドが "USER_NAME" というカラムに割り当てたい場合に使います。
この後、テーブルを作ります。
dbmap.DropTables()
err = dbmap.CreateTables()
今回は1つしかテーブルを扱っていませんが、一度に複数登録して一括で作成する事が多いと思います。
ではデータを登録しましょう。dbmap.Insert でも登録出来ますが、ここではトランザクションを使いましょう。
tx, _ := dbmap.Begin()
for i := 0; i < 100; i++ {
    tx.Insert(&Person{0, fmt.Sprintf("mattn%03d", i)})
}
tx.Commit()
今度はデータを取得してみましょう。dbmap.Get でキーを指定して1行取得する事も出来ますし、Select を使う事も出来ます。
list, _ := dbmap.Select(Person{}, "select * from person")
for _, l := range list {
    p := l.(*Person)
    fmt.Printf("%d, %s\n", p.Id, p.Name)
}
なんだか便利になってきましたね。全体のコードは以下の通り。
package main

import (
    "database/sql"
    "github.com/coopernurse/gorp"
    _ "github.com/mattn/go-sqlite3"
    "fmt"
)

type Person struct {
    Id int32
    Name string
}

func main() {
    db, err := sql.Open("sqlite3""./foo.db")
    if err != nil {
        panic(err.Error())
    }
    dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
    t := dbmap.AddTableWithName(Person{}, "person").SetKeys(true"Id")
    t.ColMap("Id").Rename("id")
    t.ColMap("Name").Rename("name")
    dbmap.DropTables()
    err = dbmap.CreateTables()
    if err != nil {
        panic(err.Error())
    }

    tx, _ := dbmap.Begin()
    for i := 0; i < 100; i++ {
        tx.Insert(&Person{0, fmt.Sprintf("mattn%03d", i)})
    }
    tx.Commit()

    list, _ := dbmap.Select(Person{}, "select * from person")
    for _, l := range list {
        p := l.(*Person)
        fmt.Printf("%d, %s\n", p.Id, p.Name)
    }
}
Go言語もだんだん仕事で使えそうな言語になってきましたね。


blog comments powered by Disqus