title: 【転載】Web フレームワーク Gin の Gin ルーティング
date: 2021-08-16 09:30:01
comment: false
toc: true
category:
- Golang
- Gin
tags: - 転載
- Go
- Golang
- Gin
- Web
- フレームワーク
- ルーティング
この記事は、Web フレームワーク Gin | Gin ルーティングから転載されています。
Web フレームワーク Gin | Gin ルーティング#
Gin は、標準的な Web サービスフレームワークであり、Restful API インターフェース仕様に従い、そのルーティングライブラリは httproute に基づいて実装されています。
このセクションでは、Gin ルーティングから始め、さまざまなルーティングシナリオで Gin を使用して実現する方法を詳しく説明します。
基本ルーティング#
Gin は、GET、POST、PUT、PATCH、DELETE、OPTIONS などのリクエストタイプをサポートしています。
例:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
route := gin.Default()
// URLが/helloのgetリクエストを設定し、簡単な応答を実装
route.GET("/get", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "これはgetメソッドの応答です!",
})
})
// 具体的な実装は別の関数として定義可能
route.POST("/post", postHandler)
route.PUT("/put", func(c *gin.Context) {
})
route.PATCH("/patch", func(c *gin.Context) {
})
route.DELETE("/delete", func(c *gin.Context) {
})
// ……
route.Run()
}
func postHandler(c *gin.Context) {
c.JSON(http.StatusOK, "これはpostメソッドの応答です!")
}
パラメータ処理#
path パラメータ#
*gin.Context
の Param 関数を使用して、リクエスト Path のパラメータを取得できます。Path のパラメータは:
で始まります。例えば、/user/:name
は、パス/user/xx
にマッチします。
例:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main() {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "男",
Age: 18,
Labels: []string{"若い", "イケメン"},
},
}
// リクエストpathにパラメータが存在
route.GET("/user/:name", func(c *gin.Context) {
// リクエストpathからパラメータを取得
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, fmt.Errorf("ユーザー[%s]が見つかりません", name))
})
route.Run()
}
クエリパラメータ#
*gin.Context
の Query 関数を使用して、パラメータを取得できます。例えば、/user?name=xcbeyond
。
例:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main() {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "男",
Age: 18,
Labels: []string{"若い", "イケメン"},
},
}
// クエリパラメータ、例:/user?name=xcbeyond
route.GET("/user", func(c *gin.Context) {
// パラメータを取得
name := c.Query("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "ユーザーが見つかりません "+name)
})
route.Run()
}
……#
ルーティンググループ#
Gin は、ルーティンググループの機能を提供し、同じルート URL プレフィックスを持つルートを分類して管理しやすくします。これは、異なるバージョンのグループに一般的です。例えば、/api/v1
、/api/v1
。
さらに、複数の階層のグループもサポートしています。
例:
package main
import (
"math/rand"
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main() {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "男",
Age: 18,
Labels: []string{"若い", "イケメン"},
},
{
Username: "niki",
Sex: "女",
Age: 16,
Labels: []string{"美しい"},
},
}
// apiグループ
api := route.Group("/api")
{
// v1グループ
v1 := api.Group("/v1")
{
v1.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "ユーザーが見つかりません :"+name)
})
}
// v2グループ
v2 := api.Group("/v2")
{
v2.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
// 見つからなかった場合、ランダムに一つ返す
user := users[rand.Intn(len(users)-1)]
c.JSON(http.StatusOK, "ユーザー["+name+"]が見つかりませんが、ユーザー["+user.Username+"]は存在します!")
})
}
}
route.Run()
}
ルーティング分割#
上記のルーティング例では、すべてのルーティング情報が同じソースファイル、関数に書かれていますが、実際のプロジェクトでは多くのインターフェースが関与し、すべてを一緒に書くのは不適切です。
実際のプロジェクトでは、ルーティングコードを分割することを好み、別のパッケージや複数のルーティングソースファイルに分割できます。
プロジェクトの規模に応じて、異なる粒度で分割できます。
(以下のルーティング分割は参考用であり、具体的なプロジェクトに応じて柔軟に調整できます!)
ルーティングを別のソースファイルまたはパッケージに分割#
ルーティングの実装を別のパッケージに分離し、プロジェクト構造をより明確にします。プロジェクト構造は次のようになります:
.
├── main.go
└── routes
└── routes.go
例の完全なソースコード:route-split-v1
/routes/routes.go
ファイルでルーティング情報を実装し、登録します:
package routes
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
var users []User
// テストの便宜上、initメソッドで直接値を設定します。実際のプロジェクトでは、一般的にデータベースなどの他の方法でデータを取得します。
func init() {
users = []User{
{
Username: "xcbeyond",
Sex: "男",
Age: 18,
Labels: []string{"若い", "イケメン"},
},
{
Username: "niki",
Sex: "女",
Age: 16,
Labels: []string{"美しい"},
},
}
}
// SetupRouter ルーティングを設定
func SetupRouter() *gin.Engine {
route := gin.Default()
route.GET("/user/:name", querUserHandler)
// その他のルーティング
return route
}
// handler
func querUserHandler(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "ユーザーが見つかりません :"+name)
}
そして、main.go でルーティング設定関数 SetupRouter を呼び出すだけです:
func main() {
route := routes.SetupRouter()
if err := route.Run(); err != nil {
fmt.Printf("サーバーの起動に失敗しました、エラー: %v", err)
}
}
ルーティングを複数のソースファイルに分割#
プロジェクトのビジネス機能が豊富になり、規模が大きくなるにつれて、すべてのルーティングを 1 つの routes.go ソースファイルに書くことは、このソースファイルがますます肥大化し、後のメンテナンスや読みやすさが不便になります。
したがって、特定の次元に基づいて複数のルーティングファイルに分割して、異なるビジネス機能を実現できます。プロジェクト構造は次のようになります:
.
├── main.go
└── routes
├── auth.go
├── routes.go
└── user.go
例の完全なソースコード:route-split-v2
routes パッケージ内で、特定の次元に基づいて複数のルーティング実装ファイルに分割します。例えば、ビジネスモジュールに基づいて、認証モジュール(auth.go)、ユーザーモジュール(user.go)などに分割し、それぞれのルーティングファイルで具体的なビジネス機能を実装し、ルーティングを登録します。
例えば、認証モジュール auth.go:
package routes
import (
"github.com/gin-gonic/gin"
)
// AuthRegister ルート登録
func AuthRegister(e *gin.Engine) {
e.GET("/auth/login", loginHandler)
e.POST("/auth/logout", logoutUserHanler)
// ……
}
// loginHandler
func loginHandler(c *gin.Context) {
}
// logoutUserHanler
func logoutUserHanler(c *gin.Context) {
}
ここで、AuthRegister 関数を定義して、このモジュールのすべてのルーティングを登録します。この関数は大文字で始まるため、グローバル関数としてパッケージ外の main.go から呼び出すことができます。
routes/routes.go では、ルーティングを設定し、すべてのモジュールのルーティングを一元的に登録します:
package routes
import (
"github.com/gin-gonic/gin"
)
// SetupRouter ルーティングを設定
func SetupRouter() *gin.Engine {
route := gin.Default()
// その他の設定
// すべてのルートを登録
UserRegister(route)
AuthRegister(route)
// ……
return route
}
main.go は前のバージョンと同様に、プログラムのエントリとして機能します:
func main() {
route := routes.SetupRouter()
if err := route.Run(); err != nil {
fmt.Printf("サーバーの起動に失敗しました、エラー: %v", err)
}
}
参考資料: