GORMをインストールしてPOSTGRESQLと連携するGOのプロジェクトを作成

# 背景 
[前回はGO言語を使って自分のPCでWEBサーバー構築](https://qiita.com/ume-bar/items/5df5f03c116418aa9d61)するという課題でしたが、今回の課題は、データベースを利用してGOから接続したデータを取り出して表示して、WEBサーバーで接続した結果を表示するというものでした。そこで、今回はオブジェクト指向プログラムとリレーショナルデータベースをつなぐ役割をしてくれるGORMを使用して構築していこうと思います。GORMとは、GOのORM(Object-relational mapping)のことをいいます。簡単にいうと、SQL文を書かずにデータベースを使える便利なものと考えてみてください。
#プロジェクトを作成してGOからユーザーテーブルを作成

プロジェクト名のフォルダを作成して、その中に入ります。プロジェクト名を**communicateWithPostgres**とします。

```
mkdir communicateWithPostgres
cd communicateWithPostgres
```
まず**go mod init**でモジュールを初期化します。GOはモジュール形式での開発が可能になったので、GOPATHの設定などは不要です。

``` 
go mod init communicateWithPostgres
```
GORMのPOSTGRESQL用ライブラリ（gorm＋driver/postgres）をインストール。[sqlite向けのインストールコマンド](https://gorm.io/docs/#Install)をpostgres用に書き換えました。

```
go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres
```

###サンプルコードはこちらを参照

- [sqlite向けのサンプルコード](https://gorm.io/docs/#Quick-Start)　
- [POSTGRESQL向けの書き方](https://gorm.io/ja_JP/docs/connecting_to_the_database.html#PostgreSQL)


```main.go
package main

import (
	"fmt"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name  string
	Email string
}

func main() {
	dsn := "host=localhost user=sampleuser dbname=blogapp port=xxxx sslmode=disable TimeZone=Asia/Shanghai"
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	db.AutoMigrate(&User{})
	fmt.Println("migrated")
}
```
GORMの関数であるAutoMigrate関数を使用し名前（Name）とEメール（Email）を持ったユーザーテーブルを作成します。[頭文字が大文字のものはPublic、頭文字が小文字のものはPrivate](https://tech-up.hatenablog.com/entry/2018/12/04/000101)なのでカラム(列)名を大文字にしています。下記のコマンドを入力して、ビルドして実行してみます。

```
go build main.go && ./main
```
その結果がこちらになります。

```
migrated
```

DBの中身を確認してみます。例として、私の環境では下記のコマンドでPOSTGRESQLにログインしております。(xxxxはDBのポート番号に合わせて変更して下さい。)

```
Applications/Postgres.app/Contents/Versions/13/bin/psql -pxxxx "blogapp"
```
`\dt`でテーブル一覧を表示すると期待通りユーザーテーブルが作成されていました。

```
blogapp=# \dt
        List of relations
 Schema | Name  | Type  |  Owner  
--------+-------+-------+---------
 public | users | table | sampleuser
(1 row)
```
#ユーザーを３名作成して、表示


```main.go
package main

import (
	"fmt"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name  string
	Email string
}

func main() {
	dsn := "host=localhost user=sampleuser dbname=blogapp port=xxxx sslmode=disable TimeZone=Asia/Shanghai"
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	db.AutoMigrate(&User{})
	fmt.Println("migrated")

	var count int64
	db.Model(&User{}).Count(&count)
	if count == 0 {
		db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
		db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
		db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
	}

	var user User
	db.First(&user)
	fmt.Println(user)
}
```
要所の説明をしていきます

```.go
var count int64 // レコードの数を入れる変数
db.Model(&User{}).Count(&count) // ユーザーのテーブルのレコード数をカウントし、結果がcount変数に入る
if count == 0 { // レコードが0の場合下記３名が作成されます
    db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
    db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
    db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
}
```
POSTGRESQL上ではこの段階でcount変数が３になっています。`select * from users;`のコマンドでテーブル内のレコード(行)を表示してみます。３名の名前とEメールが表示されました。再度、レコードを表示させようと試みても、count変数の値が３になっているので、テーブルの情報は更新されません。

```
blogapp=# select * from users;
 id |          created_at           |          updated_at           | deleted_at |  name  |      email       
----+-------------------------------+-------------------------------+------------+--------+------------------
  1 | 2021-03-27 16:31:58.707403+09 | 2021-03-27 16:31:58.707403+09 |            | user01 | xxxxxx@xxx01.com
  2 | 2021-03-27 16:31:58.709548+09 | 2021-03-27 16:31:58.709548+09 |            | user02 | xxxxxx@xxx02.com
  3 | 2021-03-27 16:31:58.710747+09 | 2021-03-27 16:31:58.710747+09 |            | user03 | xxxxxx@xxx03.com
(3 rows)
```
条件に一致した最初のレコードを取得します。Where句を使用することでデータベースに保存された大量のデータの中からレコードを検索することが可能になります。

```
var user User
	db.Where(User{Name: "user02"}).First(&user)
	fmt.Println(user)
```
ビルドして実行してみると、`migrated`とuser02が表示されました。

```
migrated
{{2 2021-03-27 16:31:58.709548 +0900 JST 2021-03-27 16:31:58.709548 +0900 JST {0001-01-01 00:00:00 +0000 UTC false}} user02 xxxxxx@xxx02.com}
```
以下の書き方もあります。カウントのエラー処理を追加しました。

```main.go
package main

import (
	"fmt"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name  string
	Email string
}

func main() {
	dsn := "host=localhost user=umehara dbname=blogapp port=5432 sslmode=disable TimeZone=Asia/Tokyo"
	
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to open database")
	}
	
	db.AutoMigrate(&User{})
	fmt.Println("migrated")
	
	var count int64
	if err = db.Model(&User{}).Count(&count).Error; err != nil {
		panic("failed to count user table")
	}
	fmt.Println(count)
	if count == 0 {
		db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
		db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
		db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
	}
	var user User
	db.Where(User{Name: "user02"}).First(&user)
	fmt.Println(user)
}
```

参考
- [MySQLとPostgreSQLコマンド比較表](https://qiita.com/aosho235/items/c657e2fcd15fa0647471)