- 筒井悠平
- 約 1,900 文字
- 4,700 View
ライブリッツの筒井です。
GoのORマッパー連載、おまけ記事です。
特に示し合わせた訳では無いのですが、RDBは全員がPostgreSQLを使っていましたね。
さて、今回の連載記事のいくつかでも言及されていた、jackc/pgx について簡単に紹介します。
GoでのPostgreSQLドライバは lib/pq が定番でしたが、現在その開発は消極的で今後機能が追加されることはめったに無いそうです。
https://github.com/lib/pq#status
一方 pgx は現在も活発に開発がなされており、GORM v2にも採用されています。
使い方の比較
lib/pq (およびdatabase/sql)と pgx の使い方を比較していきます。
pgxはドライバだけでなく database/sql 相当の機能も備えており、これ単体で使用できます。
接続
configureDatabase() が lib/pq および database/sql、configureDatabasePgx() が pgx での書き方です。以後この命名に従います。
pgx.Connect() で取得可能な pgx.Conn にはコネクションプールは含まれておらずスレッドセーフでも無いため、
database/sql と同様の使い方をする場合には pgxpool.Connect() を使用することになります。
var ( |
SQL実行
pgx では、各関数がデフォルトでcontextを受けるようになっています。そのため、database/sql の QueryContext() と pgx の Query() が同等です。
その他、ExecやBeginTxなどについても同様の使い勝手となるため割愛します。
func query() error { |
pgx の場合は1行ごとにコールバック関数を呼び出す QueryFunc() が用意されています。defer rows.Close() や for rows.Next() {} といったSnippetが不要になります。
func queryPgxEx() error { |
エラーハンドリング
pgx では Go 1.13 で追加された errors.As() が使えるようになっています。
func invalidQuery() error { |
pgx の便利機能をつかう
pgx にはLoggerを設定できます。
次のコードは pgx に zerolog を設定する例です。コネクションプールの作成時に設定します。
実行したSQLや実行時間を構造化ログとして出力できるのはなかなか便利です。
zerologの他にもzap、log15などのAdapterが用意されているようです。
https://github.com/jackc/pgx/tree/v4.13.0/log
func configureDatabasePgxWithConfig() { |
また、複数のSQLをまとめて実行できるBatch機能が用意されています。
通信にかかるオーバーヘッドを削減することが出来ますが、使い所は限定的かもしれません。
Resultの順番は、Queueに入れた順番が保持されています。
func batch() error { |
pgx と database/sql をあわせてつかう
sqlx や SQLBoiler など、 database/sql に依存するライブラリを使用する場合、pgx のドライバ (https://pkg.go.dev/github.com/jackc/pgx/v4@v4.13.0/stdlib) のみを利用できます。
この連載で紹介された ent でも使用可能です。
https://entgo.io/docs/sql-integration/#use-pgx-with-postgresql
使いたいのがsqlxであれば、pgxをサポートしている scany への乗り換えもありかと思います。
単純にドライバをすげ替えるだけであれば、インポートするドライバとドライバ名を変更するだけです。
import ( |
stdlib.RegisterConnConfig() を使えば、Loggerなどの設定もできます。
uri := "postgres://postgres:password@postgres/postgres?sslmode=disable" |
また sql.Conn.Raw() を使うと、普段は sql.DB でコネクションを扱いつつ、CopyFrom など pgx の機能が使いたいときは pgx.Conn を使う、といった使い方が可能になります。
conn, err := db.Conn(context.TODO()) |
おわりに
ここで紹介した以外にも、database/sql には無いたくさんの機能が sqlx では実装されています。
https://github.com/jackc/pgx#features
lib/pq から pgx への移行にかかる問題については、golang-migrate のこちらのIssueにおける議論がとても参考になります。
移行作業自体はとても簡単ですので、まずは試してみてはいかがでしょうか。