sqlx には、次のインターフェイスの形で非常に興味深い抽象化があります。
これらは、文字列を SQL クエリとして使用する機能を表すインターフェイスとして、ライブラリ全体で使用されます。
例えば:
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
if err != nil {
log.Fatalln(err)
}
// exec the schema or fail; multi-statement Exec behavior varies between
// database drivers; pq will exec them all, sqlite3 won't, ymmv
db.MustExec("CREATE TABLE person (first_name text)")
最後の行は、実際には次と同等です。
sqlx.MustExec(db, "CREATE TABLE person (first_name text)")
wheredb
は として使用されますExecer
。
同じように、これは:
people := []Person{}
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
次と同等です。
sqlx.Select(db, &people, "SELECT * FROM person ORDER BY first_name ASC")
wheredb
は として使用されますQueryer
。
そのため、DB
タイプを直接使用せずに、ライブラリの基礎となるフリー関数を使用する場合は、次の構造を使用してdb
、ロギングを実行するオブジェクトにラップできます。
type QueryLogger struct {
queryer sqlx.Queryer
logger *log.Logger
}
func (p *QueryLogger) Query(query string, args ...interface{}) (*sql.Rows, error) {
p.logger.Print(query, args...)
return p.queryer.Query(query, args...)
}
func (p *QueryLogger) Queryx(query string, args ...interface{}) (*Rows, error) {
p.logger.Print(query, args...)
return p.queryer.Queryx(query, args...)
}
func (p *QueryLogger) QueryRowx(query string, args ...interface{}) *Row {
p.logger.Print(query, args...)
return p.queryer.QueryRowx(query, args...)
}
そして、データベースに接続するとき:
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
if err != nil {
log.Fatalln(err)
}
ql := &QueryLogger{db, yourLogger}
sqlx.Select(ql, &people, "SELECT * FROM person ORDER BY first_name ASC")
もちろん、これは sqlx ライブラリの無料関数を使用する場合にのみ機能するため、コードに sqlx.DB 型を使用した大量の呼び出しがある場合、これはおそらく十分に便利ではありません。