【Go+TypeScript】バックエンドとフロントエンドの疎通まで

# はじめに
個人アプリを作る機会が増えてきたので、バックエンドとフロントエンド間の疎通までを簡単にまとめてみます。疎通に必要なcors設定についても触れていきます。


# 環境構築
以前に投稿した記事を元に作成しています。

https://qiita.com/does_not_exist/items/b79b3fd51ea6ef39df23

# バックエンドの実装
今回はユーザー作成機能とユーザー取得機能を実装することにします。

## モデルの作成
```go:go/src/models/model.go
package models

import "time"

type User struct {
	ID        uint   `gorm:"primaryKey"`
	Name      string
	Email     string
	Password  string
	CreatedAt time.Time
	UpdatedAt time.Time
}
```

## main.goの作成
今回はmain.goにまとめてしまいます。

```go:main.go
package main

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

var db *gorm.DB

func main() {
	// GORMの初期化
	dsn := "root:password@tcp(コンテナ名:3306)/.envで指定したdb名?charset=utf8mb4&parseTime=True&loc=Local"
	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("Failed to connect to database")
	}

	err = db.AutoMigrate(&models.User{})
	if err != nil {
		panic("Failed to migrate database")
	}

	// Ginのルーターの初期化
	router := gin.Default()
	router.Use(middleware.Cors())

	router.GET("/users/:id", getUser)
	router.POST("/users", createUser)

	router.Run(":8000")
}

func getUser(c *gin.Context) {
	userID := c.Param("id")

	var user models.User
	result := db.First(&user, userID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
		return
	}

	c.JSON(http.StatusOK, user)
}

func createUser(c *gin.Context) {
	var user models.User
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	result := db.Create(&user)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
		return
	}

	c.JSON(http.StatusCreated, user)
}
```

## cors設定について
予め設定しておかないと、フロントでaxiosを叩いても以下のエラーが発生します。

```
Access to XMLHttpRequest at 'http://localhost:8000/users/1' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

設定についてはこちらの記事を参考にさせていただきました。

https://zenn.dev/shirokikaku/books/bad8036917426f/viewer/c6fb76


```
$ docker exec -it コンテナ名 sh
$ go get "github.com/gin-contrib/cors"
```

go getができたら以下のファイルを作成します。

```go:go/src/middleware/cors.go
package middleware

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"time"
)

func Cors() gin.HandlerFunc {
	return cors.New(cors.Config{
		AllowOrigins:     []string{"http://localhost:3000"},
		AllowMethods:     []string{"GET", "POST", "PUT", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	})
}
```

ここで作成したcors.goをmain.goでimportして使います。
main.goに以下を加え、goのサーバを再起動するだけで設定できてしまいます。

```go:go/src/main.go
import (
	"github.com/gin-gonic/gin"
	"sample_go/middleware"
)
	router := gin.Default()
	router.Use(middleware.Cors())
```


## Postmanで疎通確認

以下のJSONデータをPOST /usersにリクエストしてデータが作成されていればOKです。

```
{
  "name": "John Doe",
  "email": "johndoe@example.com",
  "password": "secretpassword"
}
```

GET /users/1にリクエストして先ほど作成したデータが返ってくることも確認します。



# フロントエンドの実装

一部省略します。
ここでは画面にアクセスした際にuseEffectでaxiosを実行し、指定のユーザーデータを取得するように実装しています。

```tsx:reactapp/src/components/pages/Top.tsx

import axios from 'axios';

interface UserData {
  ID: number;
  Name: string;
  Email: string;
  Password: string;
  CreatedAt: string;
  UpdatedAt: string;
}

export const Top = memo(() => {
  const [user, setUser] =useState<UserData | null>(null)

  useEffect(() => {
    const getUserInfo = async () => {
      try {
        const res = await axios.get('http://localhost:8000/users/1');
        setUser(res.data);
        // console.log(res.data)
      } catch (error) {
        console.log(error);
      }
    };
    getUserInfo();
  }, []);

  return (
    <>
      <Box bg="red.400" textAlign="center">{user?.Name}</Box>
      <Box bg="red.400" textAlign="center">{user?.Email}</Box>
      <Box bg="red.400" textAlign="center">{user?.Password}</Box>
    </>
    )})
```

# 動作確認

localhost:3000にアクセスし、サンプルデータのユーザ名などが画面に表示されていればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/9f141975-b5dd-d524-d491-175a0bf1ee7e.png)

# おわりに
cors設定が簡単でした。