ルーティングとは、Webフレームワークのコア機能です。そのようなルーティングは、一般的に実装されている:ルーティングに応じて /
文字列配列の切断ルーティング複数に、次に前サブアレイ構成ツリー構造に同じ経路をたどる;、最初の要求に対処するとき url
に応じて /
分割し、トラバースツリーアドレッシング。
たとえば、2つのルートを定義する /user/get
、 /user/delete
我々はなります3つのノードのルーティングツリーのルートノードである構築する必要があり user
、それぞれ2つのつの子ノード get
delete
。
上述した実施形態では、ルーティングツリーの実装であり、直感的で分かりやすいです。URLは、比較、時間の複雑さ、セグメント化されます O(2n)
。
データ構造をルーティングジンは、単に再び文字列を横断するように、同様のプレフィックスツリーを使用して実装、時間複雑ですO(n)
。
もちろん、HTTPリクエストと、このルートの最適化に取り組むことは無視することができます。
エンジン
エンジンはエントリフレームで最も重要なデータ構造ジンフレーム、です。我々は、エンジンプラグインで組み立てオブジェクトサービスルーティング情報を定義するサービスを実行します。エンジンとして、それはコアエンジンのフレームワークであるとして、中国の手段「エンジン」で、全体のWebサービスは、それによって駆動されます。
そう、組み込みHTTPサーバーのGo言語を使用して基本的なHTTPサーバ、自然エンジンは唯一のビルトインHTTPサーバパッケージ - エンジンは精密機器の構造が非常に複雑であるが、エンジンの最も重要な部分があるためエンジンのオブジェクトは、非常に簡単ですそれは使用する方が便利です。
Gin
Engine
構造埋め込み RouterGroup
構造が定義され GET
、POST
そのような経路の登録方法として。
Engine
trees
論理ルーティングフィールド定義。trees
ある methodTrees
タイプ(実際には []methodTree
)、 trees
(異なる木の配列、異なるルーティング要求方法であるmethodTree
には)。
最後に、methodTree
中 root
フィールド(*node
タイプ)ルーティングツリーのルートです。そして、アドレスツリー構造をしている *node
完成プロセス。
図UML構造
trees
配列は、配列は、ツリーのルーティングの異なる要求メソッドを持つことになります。
ノード
次のようにノード構造が定義されています
type node struct {
path string // 当前节点相对路径(与祖先节点的 path 拼接可得到完整路径) indices string // 所以孩子节点的path[0]组成的字符串 children []*node // 孩子节点 handlers HandlersChain // 当前节点的处理函数(包括中间件) priority uint32 // 当前节点及子孙节点的实际路由数量 nType nodeType // 节点类型 maxParams uint8 // 子孙节点的最大参数数量 wildChild bool // 孩子节点是否有通配符(wildcard) }
パスとインデックス
上 path
と indices
、実際には、それはロジックプレフィックスツリーを使用することです。
栗の場合:
私たちは二つの経路、すなわち持っている場合は /index
、/inter
のヘッドノード {path: "/in", indices: "dt"...}
2つのノードを{path: "dex", indices: ""},{path: "ter", indices: ""}
ハンドラ
handlers
ルーティングプロセスのすべての関数に格納されているノードに対応し、ビジネスロジックを扱う場合と、そのようなものです。
func (c *Context) Next() { c.index++ for s := int8(len(c.handlers)); c.index < s; c.index++ { c.handlers[c.index](c) } }
一般的には、最後の関数を除いて、機能は、ミドルウェア、上記と呼ばれています。
ノードがあれば handlers
空の場合、それは対応するルーティングノードが存在しないことを示しています。上記で定義されたルーティングの例ルートノード対応する、 /in
存在しない、それが handlers
あります[]
。
n型
ジンは、ノードの4種類を定義しました。
const (
static nodeType = iota // 普通节点,默认
root // 根节点 param // 参数路由,比如 /user/:id catchAll // 匹配所有内容的路由,比如 /article/*key )
param
catchAll
違いは、の使用である 違い。 後のすべては、ルーティングパラメータに割り当てられます 。しかし、 複数回使用することができます。:
*
*
key
:
例えば:/user/:id/:no
それは合法的であるが、それは /user/*id/:no
ので、違法である *
すべてのコンテンツの後ろにパラメータに割り当てられます id
。
野生児
子ノードは、ワイルドカード文字(ある場合*
または:
)、そしてフィールドがあります true
。
ルーティングツリーの例
次のようにルートを定義します。
r.GET("/", func(context *gin.Context) {}) r.GET("/index", func(context *gin.Context) {}) r.GET("/inter", func(context *gin.Context) {}) r.GET("/go", func(context *gin.Context) {}) r.GET("/game/:id/:k", func(context *gin.Context) {})
その結果、ルーティングツリー写真: