gorp を使ってみた

GoでSQLを扱うのに gorpを試してみた。 GoでのDB(RDBMS)との話し方はgorp含め Qiita記事にアプローチ毎に整理されて紹介されている。

coopernurse/gorp Package gorp provides a simple way to marshal Go structs to and from SQL databases.

特に公式mattnさんの記事が参考になる。

使い方

大雑把に下の流れが必要。各種クエリにはトランザクションもサポートされている。

  1. *DbMapを取得する(DBを扱う準備をする)
  2. *TableMapを登録する(構造体をテーブルに紐付ける)
  3. 各種クエリを利用する

Webアプリなどでアクセスの度にDBをオープンしたり構造体とテーブルの紐付けしたりするのも馬鹿らしいので、 model用のパッケージなどで永続的に保持しておくのが良い。

簡単な利用例

基本的な使い方を下記のサンプルを追いながら説明する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main

import (
	"database/sql"
	"fmt"
	"os"

	"encoding/json"

	_ "github.com/mattn/go-sqlite3"
	"gopkg.in/gorp.v1"
)

func main() {
	// DBを扱う準備をする
	var (
		db, _ = sql.Open("sqlite3", "./test.db")
		dbmap = &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
	)

	// 構造体をテーブルに紐付ける
	type Action struct {
		ID        int `db:"id"`
		Name      string
		DebugInfo string `db:"-"`
	}

	// // idをPRIMARYに設定しインクリメンタルにしている
	var t = dbmap.AddTableWithName(Action{}, "action").SetKeys(true, "id")
	t.ColMap("Name").Rename("name")
	// 各種クエリを利用する
	// // テーブルをDROP & CREATE する
	dbmap.DropTables()
	_ = dbmap.CreateTables()
	// // データを追加する
	dbmap.Insert(&Action{ID: 12, Name: "HASHIRU!!", DebugInfo: "no column"})
	// // データを取得する
	list, _ := dbmap.Select(&Action{}, "SELECT * FROM action")
	var result []Action
	for _, p := range list {
		result = append(result, *p.(*Action))
	}
	res, _ := json.Marshal(result)
	fmt.Fprint(os.Stdout, string(res))
}

簡単な解説: DBを扱う準備をする

まずDBを使うために sql.Openの第一引数に "sqlite3"といったDBの名前を渡している。 これによってdatabase/sql内のdriversマップからDBドライバを選択している。

このdriversマップは事前にドライバが登録されている必要がある。 この登録作業は各パッケージの init 関数で行われる事が多い様だ。 go-sqlite3init関数の中で"sqlite3"を登録している

例えば上記ではコード内でgo-sqlite3の識別子を使わない。 でもinitを実行しdatabase/sqlから使える様にしたい。 そのため先頭でブランクインポートしている。

またdatabase/sql から扱えるドライバ一覧 もあるので何が使えるか参考にするといい。

簡単な解説: 構造体をテーブルに紐付ける

DBにはテーブルがあるものだけどgorpは AddTableなどを使い構造体をテーブルに紐付ける必要がある。 AddTableによって返される*TableMapを用いてテーブルの設定をする。

また登録する構造体にタグを付ける事でフィールドと対応する名前を指定できる。 上記のコードではdb:"id"と名前を指定している。 db:"-"と名前をハイフンにした場合、 Transientが有効になり DBに登録されないっぽい。 SetKeysはプライマリキーを決めるのに使われる。 ユニークキーを決めたり自動でバージョニングするために機能などもあるので ColumnMapについて調べると良い。

既にDB内にテーブルが存在する場合でも上記の紐付けは行う必要がある。 紐付け情報は利用後に保持する必要があるため global 変数で保持するなりが必要となる。

簡単な解説: 各種クエリを利用する

SQLを実行してみる。*DbMapのメソッドとして色々定義されている。 ここではExec,Get,Selectの差を紹介する。

Exec, Get, Select の違い

ドキュメントに明記されているけど以下の様になる

メソッド
Exec 任意のSQLを実行できるdatabase/sqlExecと一致
Get プライマリキーを利用して1行取得する
Select Select 文を渡す事でSELECT 文を実行する目的データのスライスを受け取る

ちなみにトランザクション・トレースはサポートされている。 (*DbMap)Beginで開始できる。 トランザクションに対する操作は*Transactionを読むと色々出てる。

トレース機能も紹介だけしておく。 TraceOn(prefix string, logger GorpLogger)でトレースを開始して TraceOff()でトレースを終了する。 渡すGorpLoggerPrintf()メソッドを要求するインタフェースでWriterではないので注意する。

comments powered by Disqus