Jin のような Web フレームワークでは、ルーティングはアプリケーションを構成する中心部分の 1 つです。アプリケーションが大きくなるにつれて、すべてのルートをメイン ファイルに配置すると、コードの保守と拡張が困難になります。したがって、ルーティングを抽出し、コードをよりモジュール化して組織化すると、次のような利点があります。
コードの保守性の向上: ルートを個別に抽出すると、メイン ファイルの複雑さが軽減され、コードの結合が軽減されます。これにより、コードの保守と変更が容易になり、単体テストも容易になります。
コードのスケーラビリティの向上: ルーティングが邪魔にならないため、メイン ファイルを変更することなく、新しいルーティングおよび処理関数をより簡単に追加できます。こうすることで、アプリケーションが大きくなった場合でも、拡張や保守がより簡単になります。
コードの可読性の向上: ルートをメイン ファイルから分離すると、アプリケーションの構造とロジックを理解しやすくなります。これにより、コードが読みやすく、理解しやすくなり、共同作業や保守が容易になります。
コードの再利用: ルートを抽出すると、異なるモジュールやパッケージが同じルートを共有できるようになります。このようにして、冗長なコードを削減し、コードの再利用性を向上させることができます。
したがって、ルーティングの抽出は、コードの保守性、拡張性、可読性、および再利用性を向上させることができる優れたプログラミング手法です。
では、アプリケーションをより適切に整理および管理するために、Gin フレームワークからルーターを抽出するにはどうすればよいでしょうか。
具体的な抽出方法は以下の通りです。
「routers」という名前のパッケージを作成します。
このパッケージでは、ルートを定義する「router.go」というファイルを作成します。
このファイルに、「github.com/gin-gonic/gin」ライブラリをインポートします。
ルーティングを設定するための「SetupRouter」という名前の関数を定義します。
「SetupRouter」関数で、「router」という名前の Jin エンジンを作成します。
ルーティングおよび処理機能を定義します。次に例を示します。
func SetupRouter() *gin.Engine {
router := gin.Default()
router.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello World!",
})
})
return router
}
main 関数で、「SetupRouter」関数を呼び出し、返された Jin エンジンを開始します。
func main() {
r := SetupRouter()
r.Run(":8080")
}
最後に、他のファイルで「routers」パッケージをインポートし、「SetupRouter」関数を使用してルートを設定します。
このようにして、ルーティング関数と処理関数をメイン ファイルから抽出して、アプリケーションをより適切に編成および管理できます。
さらに補足として、次のようにルーティングを抽出することもできます。
main.go ファイルで、次のように、前のルート ジャンプ ポストをグループ化し、リクエストを 1 つのステップで取得し、それらを別のフォルダーに保存します。
r.GET("/admin/index", func(ctx *gin.Context) {
new := &Article{
Title: "admin/index",
Content: "这是一个首页后台管理",
}
ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
"title": "后台首页",
"news": new,
})
})
r.GET("/admin/edit", func(ctx *gin.Context) {
new := &Article{
Title: "admin/index",
Content: "这是一个首页后台管理",
}
ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
"title": "后台首页",
"news": new,
})
})
// 这里对这两个路由请求 get请求进行分组
loginRouters := r.Group("/login")
{
loginRouters.GET("/", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login",
})
})
loginRouters.GET("/edit", func(c *gin.Context) {
c.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login/edit",
})
})
}
ここで付け加えておきますが、router.Group() メソッドの概念とは何ですか?
Jin フレームワークでは、 router.Group()
ルーティング グループを作成して、関連するルートのグループを管理できます。ルーティング グループを切断すると、次のような利点があります。
-
コードの再利用性: 同じパス プレフィックスを持つルートをグループ化して管理すると、同じプレフィックスを繰り返し定義することが回避され、コードの再利用性が向上します。
-
コードの可読性: ルーティングをグループで管理することにより、コードがより読みやすくなり、理解と保守が容易になります。
-
スケーラビリティ: 新しいルートを追加する必要がある場合、メイン ファイル内のコードを変更せずに、対応するルーティング グループに追加するだけで済み、コードのスケーラビリティが向上します。
-
ミドルウェア管理: ルーティング グループは、ミドルウェアを使用してルート グループの共通ミドルウェアをグループ化して管理し、管理とメンテナンスを容易にすることができます。
-
構成可能性: ルーティング グループを通じて、ルーティング グループ レベルのミドルウェアの設定、ルーティング グループ レベルのエラー処理機能など、さまざまなルートを個別に構成できます。
したがって、抽象化により、 router.Group()
コードの再利用性、可読性、スケーラビリティ、構成可能性、およびミドルウェア管理機能が向上し、コードがよりモジュール化され、組織化されます。
同時に、 router.Group()来
ここで抽象ルーティングを使用した後、後でコントローラー [コントローラー] メソッドを便利にするための準備をしています。
抽出が成功すると、ルート ディレクトリに routers ディレクトリが存在し、その下に複数のルートによってグループ化された単一のルーティング ファイル ( loginRouters.go のようなファイル)が存在するというルーティング ステータスが表示されます。では、これらのファイルの内部的な利点はどのようなものでしょうか? 次はコード部分です。
package routers
import (
"net/http"
"github.com/gin-gonic/gin"
)
func LoginRoutersinit(r *gin.Engine) {
loginRouters := r.Group("/login")
{
loginRouters.GET("/", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login",
})
})
loginRouters.GET("/edit", func(c *gin.Context) {
c.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login/edit",
})
})
}
}
上記は、ルーティングがグループ化された後、それぞれが独自のルート グループ化を管理し、それを別のファイルに分離するというものです。
最後は今日の最後の作業、コントローラーの取り外しです。まず第一に、なぜコントローラーがあるのか、そしてそれは何ですか? なぜコントローラーを書く必要があるのでしょうか? このような質問がある場合は、読んでください...
Jin フレームワークでは、コントローラー (Controller) とルーティング処理機能を分離するのが一般的なプログラミング手法です。コントローラーを取り外すと次のような利点があります。
-
ビジネス ロジックとルーティングの分離: ルート処理機能をビジネス ロジックから分離すると、コードをよりモジュール化して組織化できます。こうすることで、コードの管理と保守が改善され、理解と拡張が容易になります。
-
コードの再利用性の向上: コントローラーをルーティング処理機能から分離すると、コントローラー コードの汎用性と再利用性が向上します。このようにして、異なるルーティング処理関数で同じコードを繰り返し記述することを回避し、コードの再利用性を向上させることができます。
-
コードの可読性の向上: コントローラーをルート処理機能から分離すると、コードがより明確になり、理解しやすく、保守しやすくなります。このようにして、「単一責任原則」をより適切に遵守することができ、コードをよりモジュール化して組織化することができます。
-
テストの容易さ: コントローラーをルート処理機能から分離すると、コントローラーのテストが容易になります。このようにして、コントローラーとルーティング処理機能を個別にテストできるため、コードのテスト容易性が向上します。
したがって、コントローラーをルート ハンドラー関数から分離することは、コードのモジュール性、構成、再利用性、可読性、テスト容易性を向上させる、優れたプログラミング手法です。
コードのデモ部分は、上記のコードの進化と同じです。
package routers
import (
"github.com/gin-gonic/gin"
"****/controllers/login"
)
func LoginRoutersinit(r *gin.Engine) {
loginRouters := r.Group("/login")
{
loginRouters.GET("/", login.LoginControllers{}.Index)
loginRouters.GET("/edit", login.LoginControllers{}.Edit)
}
}
// 这里就对路由中函数处理,进行了抽离 放到了对应的控制器包内"****/controllers/login" 这个包就是控制器部分。
対応するコントローラーのログイン パッケージ パッケージ ログイン内のコード デモ部分:
package login
import (
"net/http"
"github.com/gin-gonic/gin"
)
type LoginControllers struct {
}
func (con LoginControllers) Index(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login-controller",
})
}
func (con LoginControllers) Edit(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login/edit-controller",
})
}
上記はコントローラーのloginControllers.goファイルの具体的なコードで、ルーティングのグループ化段階から、より詳細な分類処理を行うコントローラーへと進化し、ルーティング内の機能処理メソッドが抽象化された様子が分かります。
同時に、これも欠けているのですが、継承できる機能として、対応するコントローラファイルを同一パッケージ内で汎用的に利用できるかというと、答えは・・・。
具体的なコードで状況を説明する
logincontrollers.go ファイル
package login
import (
"net/http"
"github.com/gin-gonic/gin"
)
// 控制器继承, 和结构体 一样。
type LoginControllers struct {
BaseControllers
}
func (con LoginControllers) Index(ctx *gin.Context) {
con.success(ctx)
}
Basecontrollers.go ファイル
package login
import (
"net/http"
"github.com/gin-gonic/gin"
)
type BaseControllers struct {
}
// 控制器继承, 和结构体 一样。
func (con BaseControllers) success(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/login.html", gin.H{
"title": "login-controller--成功",
})
}
ここには何か違いがありますか、それとも同じ問題ですか?
注意深い人は、basecontroller.go ファイルから継承されたコントローラーのパッケージ名が、logincontrollers.go ファイルのパッケージ名と同じであることがわかります。
これは継承のために行われますが、パッケージでない場合はどのように継承できるのでしょうか? この問題についてはさらなる研究が必要です。
もちろん、ここで理解するのが難しい場合は、同じ理由で構造継承の基本に戻って検討してください。