LoginSignup
0
0
お題は不問!Qiita Engineer Festa 2023で記事投稿!

Go言語でDockerで立てたPostgreSQLを操作してみた

Posted at

作成:2023年7月12日
PosgreSQLの練習で、DockerでPostgreSQLを立てて、Go言語でアクセスしてみました。

docker-compose.ymlを作成

docker-compose.yml
# docker-composeで使用するバージョンを定義しています。2022年5月時点では、3.9が最新です。
version: '3.9'
# サービス (コンテナ) を定義します。
services:
  # 今回は postgres をサービスとして定義しました。
  postgres:
    # Docker Image は postgres:12-alpine を使います。postgres:12-alpine は postgres:12 と比較して、イメージサイズが小さくなっています。
    image: postgres:12-alpine
    # コンテナの名前を指定します。
    container_name: postgres
    # 環境変数を設定します。
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=testdb
    # データの永続化
    volumes:
      # postgresボリュームを/var/lib/postgresql/dataにマウントします
      - postgres:/var/lib/postgresql/data
    # ポートの指定(HOST:CONTAINER)
    ports:
      - 5432:5432
# データの永続化:ボリュームを作成します。
volumes:
  postgres:

コンテナ立ち上げ

コンテナを立ち上げて、PosgreSQLを確認します。

Terminal
$ docker-compose up -d
% docker ps
CONTAINER ID   IMAGE                        COMMAND                   CREATED              STATUS              PORTS                                       NAMES
835d849809e8   postgres:12-alpine           "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   postgres
% docker exec -it postgres bash
835d849809e8:/# psql -l
                             List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges 
-----------+-------+----------+------------+------------+-------------------
 postgres  | root  | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | root  | UTF8     | en_US.utf8 | en_US.utf8 | =c/root          +
           |       |          |            |            | root=CTc/root
 template1 | root  | UTF8     | en_US.utf8 | en_US.utf8 | =c/root          +
           |       |          |            |            | root=CTc/root
 testdb    | root  | UTF8     | en_US.utf8 | en_US.utf8 | 
(4 rows)

835d849809e8:/# 

PostgreSQLに接続してテーブル作成

PostgreSQLに接続します。

Terminal
835d849809e8:/# psql -h localhost -p 5432 -U root -d testdb
psql (12.15)
Type "help" for help.

testdb=# 

テーブルを作成します。

Terminal
testdb=# create table members (
testdb(#   id          serial primary key,
testdb(#   first_name  varchar(255),
testdb(#   last_name   varchar(255),
testdb(#   email       varchar(255),
testdb(#   accessprev  boolean
testdb(# );
CREATE TABLE
testdb=# INSERT INTO members VALUES (1, 'ichiro', 'tanaka', 'ichiro@gmail.com', TRUE);
INSERT 0 1
testdb=# INSERT INTO members VALUES (2, 'jiro', 'sato', 'jiro@gmail.com', FALSE);
INSERT 0 1
testdb=# INSERT INTO members VALUES (3, 'hanako', 'suzuki', 'hanako@gmail.com', TRUE);
INSERT 0 1
testdb=# SELECT * FROM members;
 id | first_name | last_name |      email       | accessprev 
----+------------+-----------+------------------+------------
  1 | ichiro     | tanaka    | ichiro@gmail.com | t
  2 | jiro       | sato      | jiro@gmail.com   | f
  3 | hanako     | suzuki    | hanako@gmail.com | t
(3 rows)


testdb=# 

Goのコード準備

main.go
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/lib/pq"
)

var Db *sql.DB

func init() {
	var err error
	// DB名やユーザー、テーブルは適宜適切な値を入れてください
	Db, err = sql.Open("postgres", "user=root dbname=testdb password=root sslmode=disable")
	if err != nil {
		panic(err)
	}
}

type Member struct {
	Id         int
	FirstName  string
	LastName   string
	Email      string
	AccessPrev bool
}

func main() {
	fmt.Println("----- Query 1 -----")
	rows, err := Db.Query("SELECT * FROM members ORDER BY id")
	if err != nil {
		return
	}
	for rows.Next() {
		m := Member{}
		rows.Scan(&m.Id, &m.FirstName, &m.LastName, &m.Email, &m.AccessPrev)
		fmt.Println(m)
	}
	fmt.Println()

	fmt.Println("----- Query 2 -----")
	rows, err = Db.Query("SELECT * FROM members WHERE accessprev = $1 ORDER BY id", "false")
	if err != nil {
		return
	}
	for rows.Next() {
		m := Member{}
		rows.Scan(&m.Id, &m.FirstName, &m.LastName, &m.Email, &m.AccessPrev)
		fmt.Println(m)
	}
	fmt.Println()

	fmt.Println("----- QueryRow -----")
	m := Member{}
	err = Db.QueryRow("SELECT * FROM members WHERE accessprev = $1 ORDER BY id", "true").Scan(&m.Id, &m.FirstName, &m.LastName, &m.Email, &m.AccessPrev)
	if err != nil {
		return
	}
	fmt.Println(m)
	fmt.Println()

	fmt.Println("----- Prepare -----")
	statement := "SELECT * FROM members WHERE accessprev = $1 ORDER BY id"
	stmt, err := Db.Prepare(statement)
	if err != nil {
		return
	}
	defer stmt.Close()

	rows, err = stmt.Query("false")
	for rows.Next() {
		m := Member{}
		rows.Scan(&m.Id, &m.FirstName, &m.LastName, &m.Email, &m.AccessPrev)
		fmt.Println(m)
	}
	fmt.Println()

	fmt.Println("----- Exec -----")
	_, err = Db.Exec("INSERT INTO members VALUES ($1, $2, $3, $4, $5)", 4, "takashi", "yamamoto", "yamamoto@yahoo.co.jp", "FALSE")
	if err != nil {
		return
	}
	rows, err = Db.Query("SELECT * FROM members ORDER BY id")
	if err != nil {
		return
	}
	for rows.Next() {
		m := Member{}
		rows.Scan(&m.Id, &m.FirstName, &m.LastName, &m.Email, &m.AccessPrev)
		fmt.Println(m)
	}
	fmt.Println()

}

・DB.Query:単純にクエリを実行したいときに使えます。func (*DB) Query
・Query()はRows型を返します。SQLの結果が複数行を想定しています。type Rows
 Rows型のメソッドの Next() で行があるか判断して、Scan() で値を取得しています。
・Query()関数はプレイスホルダーも使えます。SQL文に $1 などの書き方で引数で実際の値を設定できます。

main.go
rows, err = Db.Query("SELECT * FROM members WHERE accessprev = $1 ORDER BY id", "false")

 この例では第1引数の false が $1 に入ります。
・QueryRow() は Rows型を返します。一行のSQL結果が返るのを想定してScan()を使っています。func (*DB) RueryRow
・Prepare() は SQL文だけで stmtオブジェクトを作り、クエリを実行するメソッドと分けることができます。func (*DB) Prepare
・Exec() は単純にクエリを実行して、結果の行を返さないメソッドです。大抵はdelete、insertで使うそうです。func (*DB) Exec

Goの postgresドライバーをインストール

go init してから、 go get します。

Terminal
% go mod init test-postgres
go: creating new go.mod: module test-postgres
go: to add module requirements and sums:
	go mod tidy

% go get github.com/lib/pq
go: added github.com/lib/pq v1.10.9

実行

Docker上の PostgrSQL に、 Goプログラムからアクセスできました。

Terminal
% ls
docker-compose.yml	go.mod			go.sum			main.go

% go run main.go 
----- Query 1 -----
{1 ichiro tanaka ichiro@gmail.com true}
{2 jiro sato jiro@gmail.com false}
{3 hanako suzuki hanako@gmail.com true}

----- Query 2 -----
{2 jiro sato jiro@gmail.com false}

----- QueryRow -----
{1 ichiro tanaka ichiro@gmail.com true}

----- Prepare -----
{2 jiro sato jiro@gmail.com false}

----- Exec -----
{1 ichiro tanaka ichiro@gmail.com true}
{2 jiro sato jiro@gmail.com false}
{3 hanako suzuki hanako@gmail.com true}
{4 takashi yamamoto yamamoto@yahoo.co.jp false}

 % docker-compose down
[+] Running 2/2
 ✔ Container postgres           Removed                                                                                                                         0.2s 
 ✔ Network sql20230711_default  Removed                                                                                                                         0.1s 

以上、お試しでやってみました。

参考

Docker で PostgreSQL 上にデータベースを作成しよう
Go言語でSQLを実行してみる
PostgreSQLへの接続と切断
データを取得する(SELECT文)
初心者の僕がGO言語でpostgresSQLをいじるまで。
https://github.com/lib/pq
データ接続のパッケージをインポート
$ go mod init mysql-example
init関数のふしぎ #golang

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