LoginSignup
0
0

More than 1 year has passed since last update.

jackc/pgxで始めるgo+Postgres

Last updated at Posted at 2023-01-31

Go言語でjackc/pgxを使ったPostgreSQLを使う機会ができたので、最小構成でスタートさせて理解を深めようとしました。

動作環境

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

$ go version
go version go1.19.3 linux/amd64

プロジェクトの初期化

go.mod にはモジュール名とGoのバージョンのみを指定します。

$ mkdir go-postgres-sample
$ cd go-postgres-sample 
$ go mod init go-postgres-sample 
go.mod
module go-postgres-sample 

go 1.19

PostgreSQLサーバーを立ち上げる(docker-compose)

ここでは docker-compose を用いてPostgreSQLを立ち上げます。
下記の構成でファイルを用意して、ローカルで実行された postgres.go からDockerのポートフォワーディングを通してPostgreSQLコンテナーに接続します。

├── docker-compose.yml
├── go.mod
├── go.sum
├── postgres
│   └── 00-initilize-user-table.sql
└── postgres.go

docker-compose.yml は次の内容にします。接続確認ができる簡単なものです。

./docker-compose.yml
version: '3'

services:
  postgres:
    container_name: go-postgres-sample
    image: postgres:15.1-alpine
    ports:
      - 5432:5432
    volumes:
      - ./postgres:/docker-entrypoint-initdb.d
    environment:
      POSTGRES_USER: go-dev
      POSTGRES_PASSWORD: go-dev
    restart: always

PostgreSQLコンテナーの /docker-entrypoint-initdb.d に任意のSQLを置くと初回起動時に実行してくれます。

postgres/00-initilize-user-table.sql
--テーブルを作成
CREATE TABLE users (
    id serial primary key,
    screen_name text not null,
    created timestamp with time zone not null default CURRENT_TIMESTAMP,
    updated timestamp with time zone not null default CURRENT_TIMESTAMP
);

--テーブルにデータを挿入
INSERT INTO users("screen_name") VALUES ('go');

準備ができたらPostgreSQLコンテナーを立ち上げます。

$ docker compose up -d

データベースが先ほどのSQLで初期化されているかどうかは docker compose logs で確認できます。

$ docker compose logs

...

go-postgres-sample  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/00-initilize-user-table.sql

次の表示が出てデータベースが初期化されない場合は docker-compose.ymlvolumes が正しいか確認します。

/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

jackc/pgxでクエリーを実行するサンプル

Goのプログラムは次の通りです。

./postgres.go
package main

import (
	"context"
	"flag"
	"fmt"
	"os"

	"github.com/jackc/pgx/v5"
)

func main() {
	// "-uri" コマンドライン引数でPostgresの接続情報を取得
	uri := flag.String("uri", "", "Postgres URI")

	// flag.Parse()がないと値がデフォルト値になる
	flag.Parse()

	// コマンドライン引数のチェック
	if *uri == "" {
		fmt.Println("-uri option is required. \n example: postgres://username:password@localhost:5432/database_name")
		os.Exit(1)
	}

	// コネクションの作成
	fmt.Printf("Connecting: %v\n", *uri)
	conn, err := pgx.Connect(context.Background(), *uri)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
		os.Exit(1)
	}
	defer conn.Close(context.Background())

	// クエリー
	var screen_name string
	err = conn.QueryRow(context.Background(), "select screen_name from users where id=1").Scan(&screen_name)
	if err != nil {
		fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Hello, @%v!\n", screen_name)
}

パッケージの入手と動作確認

go mod tidypostgres.go にある jackc/pgx を取得し、 go.mod を更新します。そのあとに go run でビルドと実行ができます。

$ go mod tidy
$ go run postgres.go -uri postgres://go-dev:go-dev@127.0.0.1:5432/go-dev 
Connecting: postgres://go-dev:go-dev@127.0.0.1:5432/go-dev
Hello, @go!

これで動作確認できました。そのほかに pgxpool を用いてスレッドセーフなコネクションプールでPostgreSQLを操作することができます。

参考

pgx package - github.com/jackc/pgx/v5 - Go Packages
https://pkg.go.dev/github.com/jackc/pgx/v5

pgxpool package - github.com/jackc/pgx/v5/pgxpool - Go Packages
https://pkg.go.dev/github.com/jackc/pgx/v5/pgxpool

postgres - Official Image | Docker Hub
https://hub.docker.com/_/postgres

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0