PostgreSQLへの接続を標準の[database/sql]を利用した場合と
ORMのGORMを利用した場合の比較しました。
#標準
まずは、標準[database/sql]を利用した場合
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
type Sale struct {
Id string
OrderId string
}
func main() {
db, err := sql.Open("postgres", "postgres://user:pass@host:port/dbname")
if err != nil {
log.Fatalln("接続失敗", err)
}
defer db.Close()
// 取得件数を条件[$1]にする
// ?だとエラーが発生
//cmd := "select id, order_id from final_sales where id like $1"
cmd := "select id, order_id from final_sales where id like $1"
//取得するデータが1件の場合は、QueryRowも利用できる
rows, _ := db.Query(cmd, "T00%")
defer rows.Close()
var sales []Sale // 取得するデータの構造体を用意(複数取得するのでスライス)
for rows.Next() {
var tmp Sale // 取得の格納用
err := rows.Scan(&tmp.Id, &tmp.OrderId)
if err != nil {
log.Fatalln("取得失敗", err)
}
sales = append(sales, tmp)
}
for _, sale := range sales {
fmt.Println(sale.Id, sale.OrderId)
}
}
#ORM
次にORM[gorm]を利用した場合
package main
import (
"fmt"
"log"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)
// `デフォルトのテーブル名は`sales`と自動判断
type Sale struct {
Id string `gorm:"column:sale_id"`
OrderId string `gorm:"column:order_id"`
}
// 今回は、デフォルトではないので指定する
func (Sale) TableName() string {
return "final_sales"
}
func main() {
db, err := gorm.Open("postgres", "postgres://user:pass@host:port/dbname")
if err != nil {
log.Fatalln("接続失敗", err)
}
defer db.Close()
var sales []Sale // 取得するデータの構造体を用意(複数取得するのでスライス)
err = db.Where("sale_id like ?", "T00%").Find(&sales).Error
if err != nil {
log.Fatalln("取得失敗", err)
}
fmt.Println(sales)
}
#相違点
##import
database/sql
の代わりにgithub.com/jinzhu/gorm
をimportします。
##接続方法
接続を sql.Open
から gorm.Open
に変更します。
##構造体の宣言
構造体の宣言にgorm:"column:sale_id"
を付与します。
これは、gormが自動でデータ取得する際の判断に用いられます。
なお、OrderId
はスネークケースとキャメルケースの変換が自動で行われます。
そのため、以下のようにカラム名の指定が無くても問題ありません。
type Sale struct {
Id string `gorm:"column:sale_id"`
OrderId string
}
以下、サイトを参照
カラム名の指定方法
##テーブル名の指定
gormでは宣言した構造体の複数形がテーブル名として自動判断されます。
今回は自動判断の名称と違うため、テーブル名を宣言しています。
func (Sale) TableName() string {
return "final_sales"
}
以下を参照
複数形のテーブル名
##データ取得方法
ORMなので、SQLを記述する必要がなくなります。
もちろん、SQLを記述することもできます。
標準だとfor文でデータを1件ずつ取得して構造体のスライスに格納していましたが、ORMを利用すると1発で取得できます。
err = db.Where("sale_id like ?", "T00%").Find(&sales).Error
#まとめ
ローカルのSQLiteとサーバーにあるSQLSeverでSQLを別々に書いているプロジェクトを経験したことがあります。
ORMを知っていれば、このような煩わしい行為をしなくてすみそうです。
現在は、PostgreSQLへの接続情報を環境変数に用意して、環境変数を取得できない場合、ローカルの開発環境と判断し、SQLiteへ接続するようにしています。
生のSQLを記述していないため、今のところデータベースが変わってもエラーは発生していません。
ただ、通常のプロジェクトであれば、サーバーとローカルに同じデータベースを用意した方が、データベースの差異による挙動の違いも防げるので良いかと思います。
また、ORM特有の記述も覚える必要があるし。