banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

【転載】WebフレームワークGinのGinルーティング

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)
	}
}

参考資料:

  1. api-examples
  2. gin フレームワークのルーティング分割と登録
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。