GO(Gorm)  入門

# はじめに
次のPJではGOのORMであるGORMを採用するとの事だったので、自分がmacで行ったハンズオン内容を簡易的にまとめた。

GORMって何？
[公式ドキュメント](https://gorm.io/ja_JP/docs/index.html)
　→ Object-Relational Mappingの略。オブジェクトと関係（関係データベース、RDB）とのマッピングを行う。つまり、実際にSQL文を書かなくても、”直感的”にINSERT, SELECT, UPDATE, DELETEなど簡単にできちゃうイメージ。。。

実際に実機で動作確認を行うのが、早いので行った環境構築とCRUDのソースコードを追記していきます。

## 環境構築編

### MySQL
MySQLのインストール方法に関しましては、「brew mysql」で検索頂けると結構参考となる記事があるので割愛させて下さい（要望がありましたら追記致します）。

### Go ライブラリ
必要なライブラリを前もってインポートします。

``` 
% go get -u gorm.io/gorm
% go get -u gorm.io/driver/mysql
```

## 実装編

### テーブル作成

GORMには、gorm.Modelとソースコードで定義すると対象テーブルのid, create_at, updated_at, deleted_atカラムにINSERT/UPDATE/DELETE処理が行われる際に自動的にタイムスタンプを保持してくれる汎用的・使い方によっては便利な仕組みが用意されている。
https://gorm.io/ja_JP/docs/models.html#gorm-Model

上記を踏まえて、GORMのドキュメントで使われているproductsを作成する。

```createProduct.sql
CREATE TABLE データベース名.products (
	id int PRIMARY KEY auto_increment,
	code varchar(10),
	price int,
	created_at timestamp,
	updated_at timestamp,
	deleted_at timestamp
);
```

### INSERT
```gormmysql.go
package main

import (
        "log"

        "fmt"
        "gorm.io/driver/mysql"
        "gorm.io/gorm"
)

type Product struct {
        gorm.Model
        Code  string
        Price int
}

func main() {
        dsn := "ユーザー名:パスワード@/データベース名?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

        if err != nil {
                log.Fatal(err)
        }

        // Migrate the schema
        db.AutoMigrate(&Product{})

        // Create
        db.Create(&Product{Code: "D42", Price: 100})

        // Read
        var p Product
        db.First(&p, 1)
        db.First(&p, "id = ?", 1)

        fmt.Println(p)
}
```

上記のソースコードを実行して、挙動確認を行う。

``` 実行コマンド
% go build gormmysql.go
% ./gormmysql
{{1 2021-11-08 20:57:57.313 +0900 JST 2021-11-08 20:57:57.313 +0900 JST {0001-01-01 00:00:00 +0000 UTC false}} D42 100}
```

MySQLでselectして、レコードが登録されている事が確認できます。
`created_at`と`updated_at`カラムには、ソースコードを実行した日時が登録されている。

```
mysql> select * from products;
+----+------+-------+-------------------------+-------------------------+------------+
| id | code | price | created_at              | updated_at              | deleted_at |
+----+------+-------+-------------------------+-------------------------+------------+
|  1 | D42  |   100 | 2021-11-08 20:57:57.313 | 2021-11-08 20:57:57.313 | NULL       |
+----+------+-------+-------------------------+-------------------------+------------+
1 row in set (0.00 sec)
```

### UPDATE
上記でINSERTしたcodeが`D42`のpriceを500に変更する。

```gormmysql.go
package main

import (
        "log"

        "fmt"
        "gorm.io/driver/mysql"
        "gorm.io/gorm"
)

type Product struct {
        gorm.Model
        Code  string
        Price int
}

func main() {
        dsn := "ユーザー名:パスワード@/データベース名?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

        if err != nil {
                log.Fatal(err)
        }

        // Migrate the schema
        db.AutoMigrate(&Product{})

        var p Product

        // Update
        db.Model(&p).Where("code = ?", "D42").Update("price", 500)

        // Read
        db.First(&p, 1)
        db.First(&p, "id = ?", 1)

        fmt.Println(p)
}
```
MySQLでselectして、対象のレコードのpriceが`100`から`500`に更新されている事が確認できます。
`updated_at`カラムには、ソースコードを実行した日時に更新されている。

```
mysql> select * from products;
+----+------+-------+-------------------------+-------------------------+------------+
| id | code | price | created_at              | updated_at              | deleted_at |
+----+------+-------+-------------------------+-------------------------+------------+
|  1 | D42  |   500 | 2021-11-08 20:57:57.313 | 2021-11-08 21:12:14.675 | NULL       |
+----+------+-------+-------------------------+-------------------------+------------+
1 row in set (0.00 sec)
```

### DELETE
Productテーブルのidが`1`のレコードを削除する。

```gormmysql.go
package main

import (
        "log"

        "gorm.io/driver/mysql"
        "gorm.io/gorm"
)

type Product struct {
        gorm.Model
        Code  string
        Price int
}

func main() {
        dsn := "ユーザー名:パスワード@/データベース名?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

        if err != nil {
                log.Fatal(err)
        }

        // Migrate the schema
        db.AutoMigrate(&Product{})

        var p Product

        // Delete
        db.Delete(&p, 1)
}
```


MySQLでselectして、対象のレコードの`deleted_at`カラムに、ソースコードを実行した日時に登録されていることを確認。

```
mysql> select * from products;
+----+------+-------+-------------------------+-------------------------+-------------------------+
| id | code | price | created_at              | updated_at              | deleted_at              |
+----+------+-------+-------------------------+-------------------------+-------------------------+
|  1 | D42  |   500 | 2021-11-08 20:57:57.313 | 2021-11-08 21:12:14.675 | 2021-11-08 21:20:19.122 |
+----+------+-------+-------------------------+-------------------------+-------------------------+
1 row in set (0.00 sec)
```