Golangにおけるgormを利用したDB接続の方法

# 概要

私は個人的にGoを学習しています。

その中でデータベースとやりとりするのに`gorm`というORMを知りました。

なので今日は`gorm`を利用した**データベースとの接続方法**について書き残したいと思います。

# 環境

今回はDockerComposeを使用して実践していきます。

まず下記のようなDockerfileを使用します。

```Dockerfile
FROM golang:1.20-alpine3.16
ENV ROOT /app
WORKDIR ${ROOT}
RUN apk update && apk add --no-cache git
COPY go.mod go.sum ./
RUN go mod download
COPY
EXPOSE 8080
CMD["go", "run", "main.go"]
```

本番環境で利用する場合、マルチステージビルトを採用して

ビルドステージと本番用ステージを記載した方がいいと思いますが今回はスコープ外とします。

```docker-compose.yml
version: '3.8'
services:
  db:
    image: mysql:8.0
    container_name: mysql
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
    volumes:
      - ./mysql:/var/lib/mysql
    ports:
      - 3306:3306

  api:
    build:
      context: .
      target: dev
    container_name: api
    working_dir: /app
    env_file:
      - .env
    volumes:
      - .:/app
    ports:
      - 8080:8080
    depends_on:
      - db
```

各環境変数の値は`.env`ファイルで設定してください。

# gormとは

結論、`Go`で利用できる`ORM`です。

`ORM`とは**Object–relational mapping**の略で直感的にデータベースとやりとりするためのツールです。

通常Goに標準パッケージとして搭載されている`database/sql`を利用してデータベースとやりとりする際は

`SQL`を都度記載して、それを実行するという流れになります。

しかし、`gorm`を利用することで`SQL`を書かなくてもデータベースとのやりとりを実現できます。

たとえば、`Create`などを利用することで簡単にデータの作成が可能です。

もし詳しく知りたい方は下記を参照してください。

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

# 接続方法

いよいよ本題です。

データベースと接続するためには、下記のように記載します。

```database.go
package database

import (
	"fmt"
	"os"

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

var db *gorm.DB

func SetupDB() (err error) {
	connectInfo := fmt.Sprintf(
		"%s:%s@tcp(db)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		os.Getenv("DB_USER"),
		os.Getenv("DB_PASSWORD"),
		os.Getenv("DB_NAME"),
	)
	db, err = gorm.Open(mysql.Open(connectInfo), &gorm.Config{})
	if err != nil {
		return err
	}

	fmt.Println("Database connected!")
	return nil
}
```

まず、下記の部分でデータベースと接続するために接続情報を取得します。

```go
connectInfo := fmt.Sprintf(
    "%s:%s@tcp(db)/%s?charset=utf8mb4&parseTime=True&loc=Local",
    os.Getenv("DB_USER"),
    os.Getenv("DB_PASSWORD"),
    os.Getenv("DB_NAME"),
)
```

注意しなければならないのは、`tcp(db)`の部分です。

`()`内にはデータベースのホストが入ります。

今回`docker-compose.yml`でデータベース用のコンテナの`service`名を`db`に設定しているので`db`を入れればOKです。

もし、`docker-compose.yml`で`container_name`（今回で言うと`mysql`）を設定している場合は、そちらでも設定できます。

上記のように設定できたら実行してみましょう。

実行する場合は`go run`コマンドを使用しましょう。

実行するとターミナル上で下記のようになるはずです。

```shell
go: downloading gorm.io/driver/mysql v1.4.6
go: downloading gorm.io/gorm v1.24.5
go: downloading github.com/go-sql-driver/mysql v1.7.0
go: downloading github.com/jinzhu/now v1.1.5
go: downloading github.com/jinzhu/inflection v1.0.0
Database connected!
```

上記のようになれば成功です。

ただ念の為本当に接続できているかを`ping`コマンドで確認してみましょう。

`docker compose run --rm api ping db`と入力します。(接続が確認できたら`ctrl+C`で止めましょう)

```shell
$ docker compose run --rm api ping db
[+] Running 1/0
 ⠿ Container mysql  Running                                                                                                                                                  0.0s
PING db (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.998 ms
64 bytes from 172.27.0.2: seq=1 ttl=64 time=0.458 ms
64 bytes from 172.27.0.2: seq=2 ttl=64 time=0.242 ms
64 bytes from 172.27.0.2: seq=3 ttl=64 time=0.241 ms
^C
--- db ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.241/0.484/0.998 ms
```

しっかりとパケットが届いていることが確認できます。

これで接続されたことが確認できました！

# まとめ

いかがだったでしょうか。

接続自体はそれほど難しくなかったかなと思います。

今後、`gorm`を利用して学習していくので使用方法などの記事も随時更新していこうと思います！

最後まで読んでいただきありがとうございました！