我最近了解到,你可以在go中這樣做:
type Env struct{}。
func (e *Env) httpHandler(w http.ResponseWriter, r *http.Request){
/...
}
func main() {
/ ...
e := &Env{}
router := mux.NewRouter()
router.HandleFunc("/foo"/span>, e.httpHandler)
}
這對于依賴性注入是非常好的,因為當我進行單元測驗時,我可以簡單地用模擬環境呼叫httpHandler。
然而,我的問題是......假設你有:
method := e.httpHandler
在e.httpHandler已經存盤到method之后,有沒有辦法用反射或其他方式動態地改變接收器e的值?我可以改變傳入method()的引數,但似乎接收器的值被鎖定了,改變接收器的唯一方法是做e2.httpHandler。這在我的案例中是不可能的,因為我從mux路由器中提取了e.httpHandler,我只想在呼叫httpHandler之前用一個不同的接收器替換掉e。
為了了解更多情況,我正在使用 router.Walk() 來進行表驅動的測驗,在那里我遍歷每條路由,呼叫處理程式,檢查回傳的回應是否是正確的形狀,等等。然而,有些路由需要的資料庫模擬與其他路由略有不同,因此,為路由器中的所有路由使用一個萬能的模擬接收器并不理想。我想用自定義的模擬環境來動態地交換處理程式接收器,用于選擇處理程式。
uj5u.com熱心網友回復:
這就是我的想法。你怎么看?
type Env struct{
db string //應該是資料庫,只是例子。
}
func (e *Env) httpHandler(w http.ResponseWriter, r * http.Request){
}
//span>在這種情況下,通過不同的資料庫創建不同的路由器。
func newRouter(db string) *mux。 Router {
e := &Env{
db:db,
}
router := mux.NewRouter()
router.HandleFunc("/foo"/span>, e.httpHandler)
router.HandleFunc("/bar"/span>, e.httpHandler)
return 路由器
}
func TestByDatabaseA(t *testing.T) {
r := newRouter("foo")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error{
tpl, _ := route.GetPathTemplate()
if !strings.HasPrefix(tpl,"/foo"/span>){
return nil。
}
//運行測驗。
return nil
})
}
func TestByDatabaseB(t *testing.T) {
r := newRouter("bar")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error{
tpl, _ := route.GetPathTemplate()
if !strings.HasPrefix(tpl,"/bar"/span>){
return nil。
}
//運行測驗。
return nil
})
}
uj5u.com熱心網友回復:
如果你在測驗套件的整個生命周期中需要一個單一的路由器--并且由于你不能改變指標接收器或重新注冊路由處理程式--你可以嘗試包裝HandlerFunc,你可以在以后改變處理函式:
type wrapperHandler struct {
Fn http.HandlerFunc
}
func (wh *wrapperHandler) HandlerFunc() http. HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
wh.Fn.ServeHTTP(w, r) //can change `Fn` later
}
}
要使用:
// setup
router := mux.NewRouter()
wh := wrapperHandler{}。//span>稍后填寫wh.Fn。
router.HandleFunc("/foo"/span>, wh.HandlerFunc()
e := Env{ /*db1*/ }
wh.Fn = e.httpHandler
runTest(router)
e = Env{ /*db2*/ }
wh.Fn = e.httpHandler
runTest(router)
uj5u.com熱心網友回復:
在方法值中,例如由method := e.httpHandler給出,接收器被鎖定。但是對于你的用例,你不需要交換接收器。
你在指標接收器e *Env上宣告了func (e *Env) httpHandler,所以你在httpHandler中訪問的e的欄位可以從其他地方被修改,只要你保持指標在身邊。
type Env struct{
db string
}
func (e *Env) httpHandler(w http.ResponseWriter, r *http.Request){
fmt.Println(e.db)
}
func TestHandler(t *testing.T){
env := &Env{"init"}。
r := mux.NewRouter()
r.HandleFunc("/a"/span>, f.httpHandler)
r.HandleFunc("/b"/span>, f.httpHandler)
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
if p, _ := route.GetPathTemplate(); p == "/b"/span> {
env.val = "changed" ?
}
route.GetHandler().ServeHTTP(nil, nil) //列印 "init",然后 "change"。
return nil
})
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/329381.html
標籤:
下一篇:來自守護行程的錯誤回應。OCI運行時創建失敗:container_linux.go:380:啟動容器行程導致:exec:"python"。
