golang web框架設計2:自定義路由


繼續學習謝大的Go web框架設計

golang web framework 框架系列文章:

HTTP路由

http路由負責將一個http的請求交到對應的函數處理(或者一個struct的方法),路由在框架中相當於一個事件處理器,而這個時間包括

  • 用戶請求的路徑(path)(eg:/user/12, /article/1),當然還有查詢信息(eg:?id=12)
  • HTTP的請求方法(method)(GET,POST,PUT,DELETE,PATHC等)

路由的默認實現

Go的http包設計和實現路由,例子來說明

func fooHander(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

http.Handle("/", fooHandler)

http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})

log.Fatal(http.ListenAndServe(":8080", nil))

上面的例子調用的是http默認的DefaultServeMux來添加路由,需要提供2個參數,第一個參數是用戶訪問資源的URL路徑,第二個參數是即將要執行的函數。所以路由思路主要就是2點:

    1. 添加路由信息
    1. 更加用戶請求轉發到執行的函數上

Go默認的路由添加都是通過函數http.Handle和http.HandleFunc 等來添加,底層都是調用了DefaultServeMux.Handle(pattern string, handler Handler),這個函數會把路由信息存儲在一個map信息中map[string]muxEntry, 這個就解決了上面說的第一點。

Go監聽端口,然后接收到tcp連接會扔給Handler來處理,上面例子用nil參數,及是用 http.DefaultServeMux,通過DefaultServeMux.ServeHTTP函數進行調度,遍歷之前存儲的map路由信息,和yoghurt訪問的URL進行匹配,用來查詢對應的注冊函數,這就解決了上面所說的第二點。

Go默認路由的缺點

  • 1.不支持參數設定,例如/user/:uid 這種泛型類型匹配
  • 2.無法很友好的支持REST模式,無法限制訪問方法,例如上面例子中,用戶訪問/foo,可以用GET,POST,DELETE,HEAD等方式訪問
  • 3.一般網站路由規則太多,編寫頻繁。這種路由較多的可以進一步簡化,通過struct方法簡化

路由設計

針對上面Go默認路由的缺點,首先要解決參數支持就要用到正則, 第二和第三個通過一種變通方法,REST的方法對應到struct的方法中,然后路由到struct而不是函數,這樣路由時候就可以根據method來執行不同的方法。

存儲路由

根據上面說的思路,設計2個數據類型 controllerInfo,保存路徑和對於的struct,這里是一個reflect.Type類型 一個ControllerRegistor,這個是一個slice用來保存用戶添加的路由信息

type controllerInfo struct {
    regex *regexp.Regexp
    params map[int]string
    controllerType reflect.Type
}
type ControllerRegistor struct {
    routers []*controllerInfo
}

初始化ControllerRegistor

func NewControllerRegistor() *ControllerRegistor {
    return &ControllerRegistor{routers: make([]*controllerInfo, 0)}
}

ControllerRegistor對外的函數Add,添加url和對於的執行函數

func (p *ControllerRegistro) Add(pattern string, c ControllerInterfce)

在上面的函數中,第二個參數 ControllerInterfce 將在后面一節controller設計中講解,它是一個interface 類型

還有一個自動路由,實現的是Go定義的函數ServeHTTP

func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) 

完整代碼:

代碼地址 router.go


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM