Mysql,Go,Echo,GORM,sql-migrateでCRUDなAPIを作成するまで

#自己紹介
現在都内の企業でエンジニアのインターン生としてお世話になっている大学２年生です！
インターンや個人開発で学んだことや苦労したことを記事にしています！
よろしくお願いします🙇🏻‍♂️

#はじめに
Mysql,Go,Echo,GORM,sql-migrateでCRUDなAPIを作成するまでの手順を丁寧に解説していきます！
実際のAPI開発は下記記事を参考にしてみてください。

https://qiita.com/gs1068/items/194a4c35a3709d7a4342

前提として、下記の記事の環境構築ができているていで解説します！

https://qiita.com/yusuke1120925/items/810d4e1156b4da3d5391

#現在のファイル構成
早速始めていきましょう！まずは現在のファイル構成を確認してください。

```
Goパス
└── App
　　　　　　　　　└── api
     　　　　　　　├── sql
     　　　　　　　|   └── migrations 
     　　　　　　　├── dbconfig.yml
     　　　　　　　├── go.mod
     　　　　　　　└── go.sum

```
#マイグレーションファイルの作成
apiディレクトリ配下で下記のコマンドを入力してください。

```terminal:ターミナル
sql-migrate new users
```

コマンド入力後、
[現在の時間]-users.sql
というファイルがapi/sql/migrations/配下に作成される。
例えば、
2022年/1月23日/13時13分2秒
に作成すると
20220123131302-users.sql
というファイルが作成されます。
>これからマイグレーションファイルは
20220123131302-users.sql
として解説していきます。

###そもそもマイグレーションファイルとは
>マイグレーションファイルは、データベースを生成する際の設計図になるものです。
>また、マイグレーションファイルを実行することで、記述した内容に基づいたデータテーブルが生成されます。

引用

https://qiita.com/jackie0922youhei/items/09a7b081e40506f07358#:~:text=%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E3%81%AF,%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%8C%E7%94%9F%E6%88%90%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

#マイグレーションファイル(20220123131302-users.sql)の設定
```sql:20220123131302-users.sql
-- +migrate Up
CREATE TABLE IF NOT EXISTS `users` (
    --  bigint 広範囲整数 AUTO_INCREMENT データを追加した時にカラムに対して現在格納されている最大の数値に 1 を追加した数値を自動で格納することができる
    id bigint AUTO_INCREMENT NOT NULL,
    -- 可変長文字列（中に最大文字数を設定）
    first_name VARCHAR(255),
    family_name VARCHAR(255),
    email VARCHAR(255),
    -- デフォルトはCURRENT_TIMESTAMPが設定されている
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP,
    deleted_at TIMESTAMP NULL DEFAULT NULL,
    -- 主キー（重複することはできない）
    PRIMARY KEY (id)
    );

-- +migrate Down
DROP TABLE IF EXISTS `users`;
```
:::note alert
単数形のテーブルを作らないでください。
理由は後ほど解説します。
:::

#マイグレーションの実行
apiディレクトリ配下で下記のコマンドを入力してください。

```terminal:ターミナル
sql-migrate up
```
これで前回作ったデータベースにusersテーブルとmigrationsテーブルができているはずです。
できているかどうかの確認はdbeaverがおすすめです。
下記の記事を参考にしてみてください

https://qiita.com/12345/items/48f6856e32fd618ea307

#後々必要となるフォルダ、ファイルを作成
以下のファイル構造のようにフォルダ、ファイルを作成してください。

```
Goパス
└── App
　　　　　　　　　└── api
     　　　　　　　├── model
     　　　　　　　|   └── user.go
     　　　　　　　├── controllers
     　　　　　　　|   └── user.go
     　　　　　　　├── database
     　　　　　　　|   └── connect.go
     　　　　　　　├── sql
     　　　　　　　|   └── migrations 
     　　　　　　　├── dbconfig.yml
     　　　　　　　├── go.mod
     　　　　　　　├── go.sum
     　　　　　　　├── main.go
     　　　　　　　└── router.go

```
#DB接続ファイルを作成
GORMを使用し、MYSQLへの接続メソッドを定義します。

```go:connect.go
package dbconnect

import (
    "fmt"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

func Connect() *gorm.DB{
db, err := gorm.Open("mysql", "DBへの接続")
    if err != nil {
        fmt.Print("データベース接続に失敗しました。")
    }
    db.LogMode(true)
    return db
}
```
"DBへの接続"の部分は

```go
"ユーザー名:ユーザーのパスワード@/データベース名?charset=utf8&parseTime=True&loc=Local"
```
としてください。
例えば、ユーザー名がrootでパスワードが12345でデータベース名がgo_dbだとすると

```go
"root:12345@/go_db?charset=utf8&parseTime=True&loc=Local"
```

となります。

#main.goとrouter.goの作成
```go:main.go
package main

func main() {
    router := newRouter()
    router.Logger.Fatal(router.Start(":8080"))
}
```
```go:router.go
package main

import (
    "net/http"
    controller "api/controllers"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

func newRouter() *echo.Echo {
    e := echo.New()

    e.Use(middleware.CORS())

    // ルーティング
    e.GET("/", func(c echo.Context) error {
         return c.String(http.StatusOK, "Hello, World!")
     })
    e.POST("user", controller.Create())
    e.GET("user/:id", controller.UserShow())
    e.PUT("user/:id", controller.Update())
    e.DELETE("user/:id", controller.Delete())
    return e
}
```

#サーバーの立ち上げ

```
go run main.go router.go
```
これでechoサーバーが立ち上がります。

#modelファイルの作成
実際にGo側とDB側でデータのやり取りをする構造体を作成していきます。
DBのusersテーブルのデータをすべて持ってきていますが、欲しい情報だけ書けばOKです。裏を返せばここで記述のないカラムのデータはJ取得できないのでご注意ください。
追加情報で``json:"XXXXXXXX"``とすることで、Json型にして格納することができます。
　

```go:user.go
//API出力する際のDBのデータを格納する構造体を作成します。
package model

import "time"

//1文字目は大文字にしないと読み取られません
type User struct {
    Id              int              `gorm:"primary_key" json:"id"`
    First_name      string           `json:"first_name"`
    Family_name     string           `json:"family_name"`   
    Email           string           `json:"email"`
    Created_at      time.Time        `json:"created_at"`
    Updated_at      time.Time        `json:"updated_at"`
    Deleted_at      *time.Time       `json:"deleted_at"`
}
```

:::note info
ここで、マイグレーションファイルを作成した際に単数形にしてはいけない理由を解説します。
もしマイグレーションファイルでuserテーブルを作ってしまうとmodelファイルでUserモデルを作成したときに、GORM側で勝手に複数形のusersテーブルを探してしまうからです。
つまり、単数形のuserテーブルを作成してしまった場合、データベースにはuserテーブルしかないため、
　「usersテーブルなんてテーブルは存在しないよ」
と怒られてしまうということですね。
:::

#CRUDなAPI作成
ここからは下記の記事を参考にしてみてください。

https://qiita.com/gs1068/items/194a4c35a3709d7a4342

上記の記事には具体的なAPIのリクエスト方法は書いていないですが、私はインターン先でPostmanを使っているのでPostmanでリクエストをしています。
Postmanのインストール方法や、使い方などは下記記事が参考になりますので上記記事と合わせてAPIを作ってみてください。

https://qiita.com/knidik3/items/b5019b8289417fa1716a

#最後に
Mysql,Go,Echo,GORM,sql-migrateでAPIを開発するまでの手順を解説してきました。
ほとんど内容は下記記事と同じ内容ですが、全くの初心者が見て理解するには少し難しかったので、細かいところを何もわからなかったあのときの私に向けて解説しました。

https://qiita.com/gs1068/items/194a4c35a3709d7a4342

:::note warn
間違っている箇所もあるとは思いますが、教えてくださるとありがたいです。
:::
この記事がプログラミング初心者の役に立ったら幸いです。
では良い一日を👍