💻

Go言語のRest API開発 - ②GinでAPI開発

2024/06/20に公開

GoでRest APIを開発した備忘録、第2弾。

Rest API開発にはGinというフレームワークを使うのが一般的らしいので、これを使ってAPI開発していきます。

Ginインストール

以下のコマンドでginをインストールする。

$ go get -u github.com/gin-gonic/gin

Rest APIの作成

main.goを以下のように書き換え、/helloというエンドポイントのRest APIが作成できる。

main.go
package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/hello", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{
			"message": "Hello World!",
		})
	})
	r.Run(":8080") // ポート番号を指定できる
}

go runでアプリを起動し、curlコマンドで/helloを叩くと、指定したデータがJSON形式で取得できる。

$ curl http://localhost:8080/hello
{"message":"Hello World!"}

構造体をレスポンスする

以下のように構造体を定義し、それをAPIのレスポンスとして返却する。
変数定義の右にjson:"xxx"のようなタグを設定すると、JSONにしたときのkey名を指定できる。

main.go
type album struct {
	ID     string  `json:"id"`
	Title  string  `json:"title"`
	Artist string  `json:"artist"`
	Price  float64 `json:"price"`
}

main.goを以下のように書き換え、再度APIを実行し、GET /albumsのAPIを実行してみる。

main.go
package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

type album struct {
	ID     string  `json:"id"`
	Title  string  `json:"title"`
	Artist string  `json:"artist"`
	Price  float64 `json:"price"`
}

var albums = []album{
	{ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
	{ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
	{ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}

func main() {
	r := gin.Default()

	r.GET("/hello", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{
			"message": "Hello World!",
		})
	})

	r.GET("/albums", func(ctx *gin.Context) {
		ctx.IndentedJSON(http.StatusOK, albums)
	})

	r.Run(":8080")
}
$ curl http://localhost:8080/albums
[
    {
        "id": "1",
        "title": "Blue Train",
        "artist": "John Coltrane",
        "price": 56.99
    },
    {
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
    },
    {
        "id": "3",
        "title": "Sarah Vaughan and Clifford Brown",
        "artist": "Sarah Vaughan",
        "price": 39.99
    }
]

構造体をリクエストする

以下のコードを追加することで、POSTリクエストも作成することができる。

main.go
r.POST("/albums", func(ctx *gin.Context) {
	var newAlbum album

	// BindJSON()でリクエストボディのJSONを構造体にマッピングする
	if err := ctx.BindJSON(&newAlbum); err != nil {
		return
	}

	// 既存のalbumsスライスにリクエストを追加
	albums = append(albums, newAlbum)
	ctx.IndentedJSON(http.StatusCreated, newAlbum)
})

POSTリクエストしてデータを送信後、GETをリクエストすることでデータの追加を確認できる。

$ curl http://localhost:8080/albums \
    --include \
    --header "Content-Type: application/json" \
    --request "POST" \
    --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Date: Thu, 20 Jun 2024 09:10:04 GMT
Content-Length: 116

{
    "id": "4",
    "title": "The Modern Sound of Betty Carter",
    "artist": "Betty Carter",
    "price": 49.99
}

$ curl http://localhost:8080/albums
[
    {
        "id": "1",
        "title": "Blue Train",
        "artist": "John Coltrane",
        "price": 56.99
    },
    {
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
    },
    {
        "id": "3",
        "title": "Sarah Vaughan and Clifford Brown",
        "artist": "Sarah Vaughan",
        "price": 39.99
    },
    {
        "id": "4",
        "title": "The Modern Sound of Betty Carter",
        "artist": "Betty Carter",
        "price": 49.99
    }
]

ホットリロードの導入

ここで、goファイルを修正したときに、いちいちgo runし直すのは面倒だと思った。よね?
これはAirというホットリロードツールを使用すれば解決する。

まず、Airをインストール

$ go install github.com/air-verse/air@latest

.air.tomlファイル(Airの設定ファイル)を作成

$ air init

詳しい設定内容は割愛。別に特にいじらなくて良い。

airコマンドでアプリを実行できる。

$ air

これでgo run同様、アプリが実行される。
また、ファイルを修正・保存すれば、その変更が実行中のアプリに自動で反映されるようになる。

次回予告

次回はCORSの設定や、インメモリキャッシュの使い方について説明しようと思います。

↓↓↓第3回↓↓↓
未公開

参考

  • Tutorial: Developing a RESTful API with Go and Gin

https://go.dev/doc/tutorial/web-service-gin

  • Gin公式

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

  • Air

https://github.com/air-verse/air

Discussion