繼續學習謝大的Go web框架設計
golang web framework 框架系列文章:
- 7. golang web框架設計7:整合框架
- 6. golang web框架設計6:上下文設計
- 5. golang web框架設計5:配置設計
- 4. golang web框架設計4:日志設計
- 3. golang web框架設計3:controller設計
- 2. golang web框架設計2:自定義路由
- 1. golang web框架設計1:框架規划
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點:
-
- 添加路由信息
-
- 更加用戶請求轉發到執行的函數上
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)
