作成:2023年3月13日
前回までで、Goで簡易APIサーバー(GETのみ)とReactで簡易APIクライアントを試作しました。
今回はGinを使って、Goの簡易APIサーバーにPOST等の機能を追加します。
Ginを使ってGET機能作成
Ginをインストールします。
また、CORS (Cross-Origin Resource Sharing ):javascript などで API を叩く時に下記のようなエラーが出る場合のサーバーサイド側の対応として cors をインストールします。
Access to XMLHttpRequest at 'http://api.sample.com' from origin 'http://sample.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
% go mod init example/go-api
go: creating new go.mod: module example/go-api
go: to add module requirements and sums:
go mod tidy
% go get github.com/gin-gonic/gin
% go get github.com/gin-contrib/cors
GETまでコードを書きます(Github)
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-contrib/cors"
"net/http"
// "strconv"
)
type HealthData struct {
Month int `json:"month"`
Day int `json:"day"`
Weight float64 `json:"weight"`
}
var health_data = []HealthData{
{Month: 1, Day: 1, Weight: 55.5},
{Month: 1, Day: 2, Weight: 66.6},
{Month: 1, Day: 3, Weight: 77.7},
}
func getHalthdata(c *gin.Context) {
c.IndentedJSON(http.StatusOK, health_data)
}
func main() {
router := gin.Default()
// CORS 対応
config := cors.DefaultConfig()
config.AllowOrigins = []string{"http://localhost:3000"}
router.Use(cors.New(config))
router.GET("/health_data", getHalthdata)
router.Run("localhost:8080")
}
実行して、PostmanでGETできていることが確認できました。
% go run .
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /health_data --> main.getHalthdata (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on localhost:8080
[GIN] 2023/03/10 - 21:52:00 | 200 | 89.092µs | 127.0.0.1 | GET "/health_data"
ReactのAPIクライアントでもGETできました(Github)
POST機能を追加
コードを追加します(Githubのコード置き場:qiita20230311)
func postHalthdata(c *gin.Context) {
var newHalthdata HealthData
if err := c.BindJSON(&newHalthdata); err != nil {
return
}
health_data = append(health_data, newHalthdata)
}
func main() {
router.POST("/health_data", postHalthdata)
}
試しに GET してみたら、ちゃんとデータ追加されていました。
以降の機能追加のために id を追加
コードに追加(Githubのコード:qiita20230311a)
type HealthData struct {
Id int `json:"id"`
var health_data = []HealthData{
{Id:1, Month:1, Day:1, Weight:55.5},
{getData.map((data) => (
<li key={data.day}>
id : {data.id}, month : {data.month}, day : {data.day}, weight : {data.weight}
指定したidを1件GETする機能
コードを追加します(Githubのコード:qiita20230311c)
func getHealthdataById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return
}
for _, t := range health_data {
if t.ID == id {
c.IndentedJSON(http.StatusOK, t)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "the ID data does not exit!!!"})
}
func main() {
router.GET("/health_data/:id", getHealthdataById)
PATCH でデータを更新する機能を追加
コードを更新します(Githubのコード置き場:qiita20230312)
func patchHealthdata(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return
}
var health_data_patch HealthData
health_data_patch.ID = id
if err = c.BindJSON(&health_data_patch); err != nil {
return
}
for i, t := range health_data {
if t.ID == id {
health_data[i] = health_data_patch
c.IndentedJSON(http.StatusOK, health_data_patch)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "the id's health data not fount"})
}
func main() {
router.PATCH("/health_data/:id", patchHealthdata)
実行してPostmanで確認すると、id:2が更新されてレスポンスがありました。
DELETE で指定した id のデータを1件削除する機能
コードを更新します(Githubのコード置き場:qiitq20230313b)
func deleteHealthdata(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return
}
for i, t := range health_data {
if t.ID == id {
health_data = append(health_data[:i],health_data[i+1:]...)
c.IndentedJSON(http.StatusOK, gin.H{"message": "health_data(" + strconv.Itoa(id) + ") is deleted"})
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "health_data not found"})
}
func main() {
router.DELETE("/health_data/:id", deleteHealthdata)
実行 % go run . すると、 id:2 が削除されました。
以上で、5つのAPIをGoのGinで実装できました。次は簡易APIクライアントのReactを更新していきたいと思います。
router.GET("/health_data", getHealthdata)
router.GET("/health_data/:id", getHealthdataById)
router.POST("/health_data", postHealthdata)
router.PATCH("/health_data/:id", patchHealthdata)
router.DELETE("/health_data/:id", deleteHealthdata)
参考
・GoのフレームワークGinを利用してRESTfulAPIを開発する方法
・go mod init
・Golang フレームワーク Gin で CORS対応
・DockerComposeでGoのGinとMySqlの環境を作ってみた-第2弾