Go+Gin+GORMでDocker開発環境構築

# はじめに
Go言語でAPIの開発環境を構築するにあたって、Go+Gin+GORM(+air)の備忘録として残しておきます。


### GO言語とは
Google が開発したプログラミング言語であり、「Go言語」や「Golang」と表記されます。

https://go.dev/

### Ginフレームワークとは
Go言語で書かれた Web フレームワークの１つです。
パフォーマンスに優れているため、API開発にも利用されます。

https://gin-gonic.com/ja/

### GORMライブラリとは
Go言語で開発されたORM （Object-Relational Mapping）ライブラリです。

https://gorm.io/ja_JP/docs/index.html

### air
Go言語のホットリロードツールです。ホットリロードというのは「開発中のコード変更が即座に反映され、アプリを再起動することなく、リアルタイムなプレビューが可能な機能」のことです。

https://github.com/cosmtrek/air


# セットアップ

### 実行条件
- Windows 10
- Ubuntu-22.04 (WSL2)
- docker compose v2.27.0

- Golang v1.22.3
- Gin v1.10.0
- GORM v1.25.10
- air v1.52.0

- MySQL 8.0.29


今回はDockerで進めていきます。
WSLにDocker環境を構築する手順は以下を参考にしてください。

https://github.com/gmdr1024/docker-dev-doc

Dockerデーモンが起動している前提（ `sudo service docker start` ）で進めていきます。

### ディレクトリ構成

最終的には次のような構成になります。

```shell
go-gin-gorm
├── tmp
├── .air.toml
├── docker-compose.yml
├── Dockerfile
├── go.mod
├── go.sum
└── main.go
```

### プロジェクトの準備

プロジェクトを作りましょう。今回はgo-gin-gormとしています。

```shell
$ mkdir go-gin-gorm
$ cd go-gin-gorm
```

### コンテナ作成

`docker-compose.yml` を作成します。

```yml:docker-compose\.yml
services:
  go:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - .:/app
  mysql:
    image: mysql:8.0.29
    platform: linux/amd64
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: first
    volumes:
      - db-vol:/var/lib/mysql
    ports:
      - "3306:3306"
volumes:
  db-vol:
````

今回は構築と簡単な動作確認だけが目的なので、DBの設定は適当です。

次に `Dockerfile` を用意します。

```shell:Dockerfile
FROM golang:1.22.3
WORKDIR /app
RUN go install github.com/cosmtrek/air@v0.10.2
CMD ["air"]
```

準備ができたらDockerを立ち上げて開発環境にアクセスします。

```shell
$ docker compose up -d

$ docker compose exec go bash
````

### 開発準備

ここからはGO開発環境で行います。

まずはgo modを初期化します。
```shell
$ go mod init go_gin_gorm
````

.air.tomlをデフォルト設定で作成します。

```shell
$ air init
```

Ginのパッケージを取得します。
```shell
$ go get -u github.com/gin-gonic/gin@v1.10.0
 ```

これでGinの導入は完了です。 `main.go` を作成して動作確認をしてみましょう。

```golang:main.go

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    engine:= gin.Default()
    engine.GET("/", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message" : "hello world!",
        })
    })
    engine.Run(":8080")
}
```

ブラウザなどで `http://localhost:8080` にアクセスしてみましょう。
次のように表示されればOKです。

```json
{
    "message" : "hello world"
}
```

次はGORMです。Ginの導入と同じように `go get` で導入しましょう。

```golang
$ go get -u gorm.io/gorm@v1.25.10
$ go get -u gorm.io/driver/mysql
````

これで導入は完了です。こちらも念のため動作確認をしてみましょう。

main.goを修正する前に、DBの設定を行いましょう。 `MySQL Workbench` アプリやUbuntuで `docker compose exec mysql bash` によりmysql環境にアクセスするなどして、以下のようなテーブルとデータを作成してください。

◆テーブル名
results

◆テーブル構成

| カラム名 | 型 |
| ---- | ---- |
| id | INT |
| name | VARCHAR(45) |

◆テストデータ

| id | name |
| ---- | ---- |
| 1 | Test |

https://www.mysql.com/jp/products/workbench/


main.goは以下のように書き換えます（前述のものを総書き換えしましょう）

```golang:main.go
package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type Result struct {
    Id int
    Name string
}

func main() {
    engine:= gin.Default()
    engine.GET("/", func(c *gin.Context) {
        //DB接続
        dsn := "root@tcp(mysql:3306)/first?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
        if err != nil {
            panic("failed to connect database")
        }

        // レコードを1行取得
        var result Result
        db.First(&result)

        c.JSON(http.StatusOK, gin.H{
            "test" : result.Name,
        })
    })
    engine.Run(":8080")
}
```

ブラウザなどでlocalhost:8080にアクセスしてみましょう。次のように表示されればOKです。

```json
{
    "test" : "Test"
}
```


これでGo,Gin,GORMを用いた開発環境の準備は完了です。
今回はここまで。Go言語の記法は独特なので慣れるまで時間がかかりそうです。