Ginへ入門
公開日:2024-10-02
はじめに
- Go言語を学習中。今後Go言語を利用してバックエンド開発を行う予定なので、WebフレームワークのGinについて学習しました。
- 具体的にはGinを用いてRESTAPIを作成しました。
Ginとは
- Gin ドキュメント
- Gin functions
- Gin は Golang で書かれた Web アプリケーションフレームワーク。
Quick Start
mkdir bbs-project
go mod init bbs-project # モジュールの初期化(公開予定なし)
# go.modファイルが作成される
go get -u github.com/gin-gonic/gin # Ginのインストール
go get -u github.com/stretchr/testify/assert@latest # テストモジュールのインストール
# go.modファイルにginの依存関係が追加される
# go.sumファイルが作成される
vim main.go # 下記のコードを記述
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // 0.0.0.0:8080 でサーバーを立てます。
}
- Postmanより
http://localhost:8080/ping
にGETリクエストでアクセスすると、{"message":"pong"}
が返ってくることを確認。
BBSを元にしたAPIの作成
- Github このリポジトリにまとめています。
- BBSプロジェクト で作成したAPIをGinを用いて作成しました。
- プロジェクトはMVCモデルで作成。
- Model層 .. models/内に記載。データ構造体を定義してデータベースとのやり取りを行う。
- Controller層 .. controllers/内に記載。リクエストを受け取り、適切な処理を行う。
- View層 .. views/内に記載。REST APIのためViewは不要だが、返却するJSONをViewとして扱う。
- ルーティングはroutes/内に記載。
- main.goがエントリーポイント。
- テストコードはtest/内に記載。
- ディレクトリ構造は以下の通り。
├── go.mod ├── go.sum ├── main.go ├── models │ └── post.go ├── views └── post_view.go ├── controllers │ └── post_controller.go ├── routers │ └── router.go ├── test │ └── post_controller_test.go ├── openapi.yaml └── README.md
- 呼び出しについて
- main.goを起動することで、ルーティングを起動。
- ルーティングはcontrollers/内のコントローラーを呼び出し、処理を行う。
- コントローラーはmodels/内のモデルを呼び出し、データベースとのやり取りを行う。
- コントローラーではviews/内のビューを呼び出し、JSONを返却する。
├── main.go └── routers/router.go └── controllers/post_controller.go ├── models/post.go └── views/post_view.go
各ファイルの説明
-
main.go
- ルーティングを設定し、サーバーを起動する。
package main import ( "bbs-project/routers" ) func main() { r := routers.SetupRouter() r.Run(":8080") }
-
routers/router.go
- GET, POST, DELETE, PUTのエンドポイントを設定する。
package routers import ( "bbs-project/controllers" "github.com/gin-gonic/gin" ) // ルーティングの設定 func SetupRouter() *gin.Engine { r := gin.Default() // /v1/api に関連するエンドポイントをグループ化 api := r.Group("/v1/api") { api.GET("/list", controllers.GetPosts) api.GET("/detail/:id", controllers.GetPostDetail) api.POST("/create", controllers.CreatePost) api.DELETE("/delete/:id", controllers.DeletePost) api.PUT("/update/:id", controllers.UpdatePost) } return r }
-
controllers/post_controller.go
- リクエストを受け取り、適切な処理を行う。
- 投稿一覧取得の例
- c.Queryでクエリパラメータを取得している。
- strconv.Atoiで文字列を数値に変換し、数値でない場合はエラーを返す。
package controllers import ( "bbs-project/models" "bbs-project/views" "net/http" "strconv" "github.com/gin-gonic/gin" ) // 投稿一覧取得のコントローラ func GetPosts(c *gin.Context) { // クエリパラメータの取得 pageStr := c.Query("page") perPageStr := c.Query("per_page") // ページ数の確認 page, err := strconv.Atoi(pageStr) if err != nil || page < 1 { views.RenderError(c, http.StatusBadRequest, "Invalid page parameter", "The 'page' parameter must be a positive integer.") return } // 1ページあたりの表示数の確認 perPage, err := strconv.Atoi(perPageStr) if err != nil || perPage < 1 { views.RenderError(c, http.StatusBadRequest, "Invalid per_page parameter", "The 'per_page' parameter must be a positive integer.") return } start := (page - 1) * perPage end := start + perPage if start >= len(models.Posts) { views.RenderPosts(c, []models.Post{}) return } if end > len(models.Posts) { end = len(models.Posts) } views.RenderPosts(c, models.Posts[start:end]) }
実行と確認方法
# 実行
go run main.go
-
Postmanより以下のエンドポイントにGETリクエストを送信することで、APIの動作を確認できる。
-
POST http://localhost:8080/v1/api/create
# Request Body { "title": "aaa", "content": "bbb" }
-
PUT http://localhost:8080/v1/api/update/2
# Request Body { "title": "aaa", "content": "bbb" }
テスト
-
test/post_controller_test.go
にテストコードを記述し、関数をTest~
で始め、go test
コマンドでテストを実行することが可能 -
今回はhttpcodeが200であることを確認するテストを記述。
# テスト cd ~/bbs-project/test go test [GIN] 2024/10/02 - 19:06:00 | 200 | 52.748µs | | POST "/v1/api/create" [GIN] 2024/10/02 - 19:06:00 | 200 | 19.998µs | | GET "/v1/api/list?page=1&per_page=2" [GIN] 2024/10/02 - 19:06:00 | 200 | 2.344µs | | GET "/v1/api/detail/2" [GIN] 2024/10/02 - 19:06:00 | 200 | 9.628µs | | DELETE "/v1/api/delete/2" [GIN] 2024/10/02 - 19:06:00 | 200 | 16.591µs | | PUT "/v1/api/update/2" PASS ok bbs-project/test 0.004s
Golang/Ginの学習メモ
gin.Default()
でロガーとリカバリーのミドルウェアがすでにアタッチされたEngineインスタンスを返す。gin.New()
では空のEngineインスタンスを返す。gin.Context
ではミドルウェア間で変数を渡したり、フローを管理したり、リクエストのJSONを検証したり、JSONレスポンスをレンダリングしたりすることができる。gin.H
はmap[string]interface{}
へのショートカット。import "log"
でlog.Println()
などのログ出力が可能。Group
でエンドポイントをグループ化することができる。ShouldBindJSON
でリクエストボディを構造体にバインドし、受け取ったデータを構造体に格納できる。c.JSON
で構造体をJSON形式に変換して返却することができる。
まとめ
- Ginを用いてREST APIを作成しました。プロジェクトはMVCモデルで作成し、メンテナンス性を高めました。
- 今後としては、データベースの連携、Ginの機能を活用したAPIの拡張を行っていきたいです。