オンラインのDBサービスのElephantSQL（PostgreSQL）を使う

# はじめに
バックエンド開発やAPI開発をしているとデータベースで動作の確認などをしたいことはよくあると思います。
しかしちょっとしたことを手元環境で試したい時に、わざわざ開発用のデータベースで行うというのは難しかったりしますよね。
ElephantSQLは、そんな時に利用できるクラウドで手軽に利用することができるPostgreSQLデータベースです。もちろん商用目的としたデータベースとしても利用することはできます。

今回はGoでElephantSQLに接続して、テーブルデータ取得し表示できるところまで紹介します。

# ElephantSQLとは
簡単にいうと、クラウド上で利用できるPostgreSQLデータベースのホスティングサービスです。
インストール・最新バージョンへのアップグレード・バックアップなどPostgreSQLの管理タスクをすべて行ってくれます。つまり、ユーザはボタンをクリックしていくだけですぐにデータベースが使えるようになります。
[有料プラン](https://www.elephantsql.com/plans.html)も用意されていますが、開発時にちょっとした確認・データベースの学習などの大きなサイズが不要なら [無料プラン](https://customer.elephantsql.com/instance/create?plan=turtle)（制限あり）で十分だと思います。


https://www.elephantsql.com/

# 動作環境
- macOS 11.2.2
- Google Chrome

# セットアップ
基本的には、公式サイトの[Getting started](https://www.elephantsql.com/docs/index.html) の通りに進めます。

## 1. ログイン

サインアップなどユーザ登録せずとも、GithubアカウントやGoogleアカウントも持っているなら、既存のアカウントでログインでき始めることができます。

![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/e56b1a91-e264-b647-34f4-bc7343b3ce36.png)

## 2. インスタンス作成
ドキュメントにありますが、大きなサイズで必要な場合はクレジットカードの登録が必要です。今回は無料枠で進めます。

- 右上にある [+ Create New Instance] ボタンを押します。
![instance-create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/0ea6a70e-cd79-8833-cb33-3ae2a42647a1.png)

- プラン選択
デフォルトが無料の「Tiny Turtle (Free)」が選択されています。

![select-plan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/87783e76-1edd-e907-1f9a-77de7a12813a.png)

  * Name: インスタンスの名前
  * Plan: プラン（特に必要がなければそのまま無料プランでよい。）
  * Tags: タグ（プロジェクト間でインスタンスを分けるために利用するみたいです。未設定でも大丈夫そう。）

- リージョン選択
右下の [Select Region] を押します。
AWSかGoogleCloudのリージョンを選択できます。アジア圏だと、Hong KongまたはSydneyだけみたいです。

![region-select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/a29a9d2e-2f75-2c28-6217-212348abacd0.png)

- 確認
右下の [Preview] を押します。

設定した項目を確認します。問題なければ、[Create Instance] を押して作成します。

![preview-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/4d77383a-a245-0497-5ea4-f6363727bbed.png)

設定は基本的にここまでで終わりました。この状態で、Postgresデータベースが使えるようになっています。

インスタンス詳細が↓の画像のように出来上がっています。

![detail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/769b3200-05ed-dbcb-b468-6f4b354e368f.png)

接続用のURLが `postgres://username:password@hostname/databasename` の形式で表示されています。

## 3. テーブル作成
テーブルを作成するには、サイドメニューの [Browser] を押します。
SQLが実行できる↓のような画面が表示されますので、そこでテーブルを作成します。

![SQL-Browser.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/6109e277-4608-cf58-d703-abba4172149e.png)

適当にテーブルを作成してみます。 
＊PostgreSQLのサイトから[引用](https://www.postgresql.jp/document/10/html/tutorial-table.html)させてもらいました。


```sql
CREATE TABLE weather (
    city            varchar(80),
    temp_lo         int,           -- 最低気温
    temp_hi         int,           -- 最高気温
    prcp            real,          -- 降水量
    date            date
);

CREATE TABLE cities (
    name            varchar(80),
    location        point
);
```

作成したテーブルを確認します。以下のクエリを実行します。

```sql
SELECT *
FROM pg_catalog.pg_tables
WHERE schemaname != 'pg_catalog' AND 
    schemaname != 'information_schema';
```
確認できました。

![result_qry.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4181/2ebc32dc-53e8-ccdf-8f36-a922dada1287.png)

普段使っている PostgreSQLのGUIクライアントからでも接続して操作ができます。筆者の場合は、[Postico](https://eggerapps.at/postico/)、[SQL Studio Pro](https://www.sqlprostudio.com/)で接続ができました。

# Databaseに接続する
今回はGoで接続してテーブルデータを出力したいと思います。
[ドキュメントページ](https://www.elephantsql.com/docs/go.html) にはいろいろな言語での接続サンプルが用意されているので、サンプルを利用して少し手を加えながらコードを記述してみます。

- 事前に cities テーブルにデータを登録しておきます。
- サンプルは [jet](https://github.com/eaigner/jet) というORMを利用しているのでそのまま利用します。
- 環境変数を簡単に利用できる [godotenv](https://github.com/joho/godotenv) というパッケージを利用します。

godotenvでは .env ファイルに環境変数を記述しておきます。


```text:.env
// ElephantSQLのインスタンス詳細で確認したものです。
ELEPHANTSQL_URL=postgres://user:pass@host/db?options
```

```golang:main.go
package main

import (
    "log"
    "os"

    "github.com/eaigner/jet"
    "github.com/joho/godotenv"
    "github.com/lib/pq"
)

func main() {
    
    // godotenvを利用して環境変数を読み込みます。
    if err := godotenv.Load(); err != nil {
	log.Fatal("Error loading .env file")
    }

    // ここでELEPHANTSQL_URLを設定しています。
    // 環境変数からURLを取得しています。
    pgUrl, err := pq.ParseURL(os.Getenv("ELEPHANTSQL_URL"))
    if err != nil {
        log.Fatal(err)
    }

    db, err := jet.Open("postgres", pgUrl)
    if err != nil {
        log.Fatal(err)
    }

    // テーブルに合わせてstructを定義します。
    var cities []*struct {
        Name     string
        Location string
    }
    
    if err := db.Query("SELECT * FROM cities").Rows(&cities); err != nil {
		log.Fatal(err)
    }

    for _, city := range cities {
        // コンソールに出力します
        log.Printf("Name: %v, Point: %v\n", city.Name, city.Location)
    }
}
```

コンソールに、登録データが出力されました。

```terminal
➜  elephant go run main.go
2021/06/19 13:56:13 Name: tokyo, Point: (35.681235999999998,139.76712499999999)
2021/06/19 13:56:13 Name: shibuya, Point: (35.661971000000001,139.70379500000001)
2021/06/19 13:56:13 Name: osaka, Point: (34.693725000000001,135.50225399999999)
2021/06/19 13:56:13 Name: nagoya, Point: (35.181451000000003,136.90655699999999)
2021/06/19 13:56:13 Name: sapporo, Point: (43.061771,141.35445100000001)
2021/06/19 13:56:13 Name: fukuoka, Point: (33.590184000000001,130.401689)
2021/06/19 13:56:13 Name: kobe, Point: (34.690080999999999,135.19563099999999)
2021/06/19 13:56:13 Name: new york, Point: (40.712775000000001,-74.005972999999997)
2021/06/19 13:56:13 Name: paris, Point: (48.856614,2.3522219999999998)
2021/06/19 13:56:13 Name: stockholm, Point: (59.329324,18.068580999999998)
2021/06/19 13:56:13 Name: london, Point: (51.507351,-0.12775800000000001)
2021/06/19 13:56:13 Name: rome, Point: (41.902783999999997,12.496366)
2021/06/19 13:56:13 Name: sydney, Point: (-33.868819999999999,151.20929599999999)
```

# まとめ

dockerなどでも手軽にできるとは思いましたが、それ以外の選択肢として利用する価値はあると思いました。なにより導入ハードルが低いところと無料で利用できるという点が素敵です。開発時にちょっとした確認などを出来る環境があると作業効率も上がりまし、コストもかかりません。またデータベースの学習に使うということも有り得そうです。セットアップも簡単なので暇な時に是非試してみてください。

[コード](https://github.com/nakashimanh/elephant)をGithubに公開中。