はじめに
GoからDBをさわるためのxoってツールがある。いまいち、使い方がよくわかってなかったので、試してみた。
xo
DBをさわるときに便利なコードを、スキーマから生成してくれるらしい。
xo is a command-line tool to generate Go code based on a database schema or a custom query.
環境
このとき作った環境を使う
Dockerを使ってPostgreSQL+Goの開発環境を作ってみた - Qiita
インストール
READMEにしたがって実行した。
go get -u golang.org/x/tools/cmd/goimports
go get -u github.com/xo/xo
ファイル生成
QuickstartにPostgreSQLのやりかた書かれてた。
models
フォルダを作る前にやったら、フォルダがないとおこられた。
/go/src/work/xo# xo pgsql://root@db/db1 -o models
error: output path must be a directory and already exist when not writing to a single file
次は、sslが有効になってないとおこられた。PostgreSQL立ち上げるときの設定かな。disableにしといたらいいか。
/go/src/work# xo pgsql://root@db/root -o models
error: pq: SSL is not enabled on the server
これで、models
フォルダにファイルを生成できた。
xo pgsql://root@db/root?sslmode=disable -o models
使ってみる
生成されたコードを使ってみる。
まず、パッケージ名は生成先のフォルダ名になる。
// Package models contains the types for schema 'public'.
package models
ここを参考にさせてもらった。
DBから直接golangのモデルを生成するxoのご紹介 — そこはかとなく書くよん。
パスは$GOPATH
からのパスで指定したらいけた。ここらへん、よくわかってない。
package main
import (
"database/sql"
"work/models"
_ "github.com/lib/pq"
)
func main() {
db, err := sql.Open("postgres", "host=db port=5432 user=root sslmode=disable")
defer db.Close()
if err != nil {
panic(err)
}
e := &models.Employee{
EmpNumber: sql.NullInt64{
Int64: 4432,
Valid: true,
},
}
if err = e.Insert(db); err != nil {
panic(err)
}
}
実行してみる。
go run main.go
行けたっぽい。
Posticoで確認
PosticoっていうGUIクライアントで確認した。
データ入ったみたい。
よかったよかった。
生成ファイルの中身
構造体が作られてる。json
のタグもある。
// Employee represents a row from 'public.employee'.
type Employee struct {
EmpID int `json:"emp_id"` // emp_id
EmpNumber sql.NullInt64 `json:"emp_number"` // emp_number
// xo fields
_exists, _deleted bool
}
Insert()
の中身はSQLでクエリが書かれてるだけ。
// Insert inserts the Employee to the database.
func (e *Employee) Insert(db XODB) error {
var err error
// if already exist, bail
if e._exists {
return errors.New("insert failed: already exists")
}
// sql insert query, primary key provided by sequence
const sqlstr = `INSERT INTO public.employee (` +
`emp_number` +
`) VALUES (` +
`$1` +
`) RETURNING emp_id`
// run query
XOLog(sqlstr, e.EmpNumber)
err = db.QueryRow(sqlstr, e.EmpNumber).Scan(&e.EmpID)
if err != nil {
return err
}
// set existence
e._exists = true
return nil
}
おわりに
雰囲気わかった。思ったよりシンプルやった。
go mod
とかerror
とかgomock
がよくわかってないので、そっちももうちょい試してみたい。sqlx
ってのも。