手把手和你一起實現一個Web框架實戰——EzWeb框架(四)[Go語言筆記]Go專案實戰

學習先生發表於2021-08-20

手把手和你一起實現一個Web框架實戰——EzWeb框架(四)[Go語言筆記]Go專案實戰

程式碼倉庫:
github
gitee
中文註釋,非常詳盡,可以配合食用

這一篇文章主要實現路由組功能。實現路由組對路由進行更便利的管理,如應用中介軟體的應用。

一、路由組設計

這裡進行的設計是以路由組字首來進行區分的。巢狀

實現一個r.Group(prefix string)函式來構造路由組,使之在呼叫GETPOST等方法進行路由註冊時,擁有共同的字首。GETPOST等方法註冊路由時呼叫了addRoute()方法,即如果我們在路由組中做註冊路由的方法時,我們註冊的路由是"Group.prefixt+last(這裡的last是路由組內註冊方法的路徑)"。

type RouterGroup struct {
	prefix      string
	middlewares []HandlerFunc // 用於儲存分組的中介軟體
	engine      *Engine       // 這裡實現的巢狀讓其擁有了engine的全部屬性,所有的分組都使用了Engine例項,可以通過engine間接的訪問各種介面
}

// Engine 實現了"net/http"標準庫中的 Handler 介面中的ServeHTTP方法
type Engine struct {
	*RouterGroup	//巢狀,讓Engine擁有RouterGroup的全部屬性,這樣做體現在我們使用r.Group()建立路由組的時候
	groups []*RouterGroup
	//用於儲存路由處理方法
	//key是方法型別加路徑,value是使用者的處理方法
	router *router
}

當我們呼叫r.Group(prefix string),我們就構建了一個RouterGroup例項

engine *Engine

這讓它們擁有一個共同的處理例項engine,當呼叫addGroup方法,為某個路由組路由註冊時,我們可以通過先對"路由組字首+剩餘path",這樣的處理,再通過呼叫group.engine.router.addRoute(method, path, handler)進行路由註冊。

func (group *RouterGroup) addRoute(method string, last string, handler HandlerFunc) {
   path := group.prefix + last
   group.engine.router.addRoute(method, path, handler)
}

二、方法修改

這裡體現了為什麼在RouterGroup結構體中要巢狀一個engine *Engine。我們在使用這個路由組功能的demo是這樣的。

r := Ez.New()
api := r.Group("/api")
{
   api.POST("/hello", func(c *Ez.Context) {
      c.JSON(http.StatusOK,Ez.H{
         "message" : "hello",
      })
   })
}

r是一個Engine指標變數,我們的Group()方法,是屬於RouterGroup的,在Engine結構體中巢狀了*RouterGroup使得我們可以直接呼叫它。而我們通過r.Group("/api")建立的這個api變數是一個Routergroup指標變數,我們們想要使用api.POST註冊路由的時候,我們在Routergroup結構體中巢狀的engine *Engine就起了相關的作用。

// New Engine
func New() *Engine {
	//新建一個engine例項
	engine := &Engine{router: newRouter()}
	engine.RouterGroup = &RouterGroup{engine: engine}
	engine.groups = []*RouterGroup{engine.RouterGroup}
	return engine
}
// Group 新建Group
func (group *RouterGroup) Group(prefix string) *RouterGroup {
   engine := group.engine
   newGroup := &RouterGroup{
      prefix:      group.prefix + prefix,       //字首
      engine:      engine,               //任何路由組都共享一個處理例項
   }
   engine.groups = append(engine.groups, newGroup)
   return newGroup
}
// engine.router.addRoute 方法封裝在router中
func (group *RouterGroup) addRoute(method string, last string, handler HandlerFunc) {
   path := group.prefix + last
   group.engine.router.addRoute(method, path, handler)
}
func (group *RouterGroup) GET(path string, handler HandlerFunc) {
   group.addRoute("GET", path, handler)
}

func (group *RouterGroup) POST(path string, handler HandlerFunc) {
   group.addRoute("POST", path, handler)
}

demo測試:

/*
@Time : 2021/8/16 下午4:01
@Author : mrxuexi
@File : main
@Software: GoLand
*/
package main

import (
	"Ez"
	"net/http"
)
func main() {
	r := Ez.New()

	api := r.Group("/api")
	{
		api.POST("/hello", func(c *Ez.Context) {
			c.JSON(http.StatusOK,Ez.H{
				"message" : "hello",
			})
		})
		api.GET("/login", func(c *Ez.Context) {
			c.JSON(200,Ez.H{
				"name" : c.PostForm("name"),
			})
		})
	}


	r.Run(":9090")
}

成功!

參考:

[1]: https://github.com/geektutu/7days-golang/tree/master/gee-web ""gee""
[2]: https://github.com/gin-gonic/gin ""gin""

相關文章