15

フレームワーク以外の Go スタックをsqlxで使用しており、MySQLを Web プロジェクトに使用しています。

デバッグのためにすべての送信 SQL ステートメントをログに記録したいと考えています。これを行うことは可能ですか?うまくいけば、次のような出力が得られることを期待しています (Rails プロジェクトからコピー):

  User Load (94.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'bondnewyork' LIMIT 1
  User Load (16.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'mkovarik' LIMIT 1
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'mkovarik' LIMIT 1
  User Load (0.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
  User Load (0.4ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
4

1 に答える 1

15

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 型を使用した大量の呼び出しがある場合、これはおそらく十分に便利ではありません。

于 2015-10-09T15:26:52.880 に答える