我正在學習 Go,目前正試圖了解julienschmidt 的 httprouterhttp路由器的實際作業原理和方式。尤其是 router.HandlerFunc() 是如何作業的。
Go 的 http 包:
http.Handler:處理程式是一個介面。任何具有相同方法簽名的型別,即 ServeHTTP(w,r) 都實作了一個處理程式。http.Handle: http.Handle 是一個有兩個引數的函式。1)字串匹配請求路徑,2)Handler,呼叫它的ServeHTTP()方法。http.HandlerFunc: 一個自定義的函式型別,帶有函式簽名(ResponseWriter, *Request)和自己的ServeHTTP(w,r)方法,滿足http.Handler介面。
現在,如果我需要使用一個函式,例如。滿足為 HandlerFunc 的 Bar(ResponseWriter, *Request),在 http.Handle 中,我鍵入 caste/covert 函式到 http.HandlerFunc,然后在 http.Handle 中使用它。像這樣:
func Bar(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("My bar func response"))
}
...
mf := http.HandlerFunc(Bar)
http.Handle("/path", mf)
- 查看http.HandleFunc 源代碼,這就是 http.HandleFunc() 的作業原理。它期望一個函式作為 (w ResponseWriter, r *Request) 的簽名并對該函式進行型別轉換。
像這樣:
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
julienschmidt 的 httprouterhttp
查看router.HandlerFunc() 的原始碼
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
- 它不期望像 http.HandleFunc() 那樣具有適當簽名(ResponseWriter,*Request)的函式,而是期望 http.HandlerFunc。
- 同樣沒有將函式型別轉換/轉換為 HandlerFunc 型別,它只是將函式傳遞給另一個函式 router.Handler(method, path string, handler http.Handler),它再次需要一個 Handler。
所以我可以毫無問題地執行這段代碼:
router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar is not type casted/converted to a HandlerFunc
我可以理解將 Bar 型別轉換為 HandlerFunc,然后將其傳遞給 router.HandlerFunc()。
您能否解決我的一些疑問:
- 如果不將 Bar() 型別轉換為 HandlerFunc,如何滿足 router.HandlerFunc() 的 HandlerFunc 型別?
- 如果 router.Handler() 需要一個 http.Handler 型別,那么 Bar() 沒有對 http.HandlerFunc 的型別轉換如何滿足 router.Handler() 的處理程式?
- 我錯過了什么?
uj5u.com熱心網友回復:
- “如果不將 Bar() 型別轉換為 HandlerFunc,如何滿足 router.HandlerFunc() 的 HandlerFunc 型別?”
表達方式
router.HandlerFunc(http.MethodPost, "/path", Bar)
符合可分配性規則:
V并且T具有相同的基礎型別,并且至少有一個V或T不是命名型別。
Bar函式的型別和型別http.HandlerFunc具有相同的底層型別,并且Bar型別沒有命名。因此,您可以將 (assign)Bar作為handler引數傳遞給httprouter.Router.HandlerFunc而無需顯式轉換。
- “如果 router.Handler() 需要一個 http.Handler 型別,那么 Bar() 沒有型別轉換到 http.HandlerFunc 怎么會滿足 router.Handler() 的處理程式?”
在下面的方法定義中
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
沒有,只有型別為的引數 ,并且該型別確實實作了介面。所以這個說法是完全合法的。Barhandler http.HandlerFunchttp.Handlerr.Handler(method, path, handler)
- “我錯過了什么?”
看上面。
uj5u.com熱心網友回復:
查看 HandlerFunc 的定義
type HandlerFunc func(ResponseWriter, *Request)
以及您的功能的簽名
(w http.ResponseWriter, r *http.Request)
你不需要在這里轉換。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/493488.html
標籤:去
上一篇:如何模擬呼叫io.Copy的函式
