2016-10-06 10 views
0

我正在嘗試執行expressjs之類的特性至httprouter包。 我創建了一個結構type mounterGolang httpRouter返回與切片函數一起使用時的最後一個響應

type Mounter struct { 
    BasePath string 
    Routes []*Route 
} 

Route結構代表子路徑

type Route struct { 
    Path string 
    Method string 
    Func Handle 
} 

type Handle func(http.ResponseWriter, *http.Request, Params)

type Params interface{}

我有一個NewRoutes功能這是我想主要的事情來自expressjs新航線的港口呢同樣的事情express.Router

func NewRoutes(base string) (mounter *Mounter) { 
    mounter = &Mounter{ 
     BasePath: base, 
    } 
    return 
} 

和我下*Mounter

//GET request handler 
func (mounter *Mounter) GET(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "get", Func}) 
} 

//POST request handler 
func (mounter *Mounter) POST(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "post", Func}) 
} 

//PUT request handler 
func (mounter *Mounter) PUT(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "put", Func}) 
} 

//DELETE request handler 
func (mounter *Mounter) DELETE(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "delete", Func}) 
} 

get post put delete方法,最後我有一個安裝方法,其安裝路由器的實際路由器

func (mounter *Mounter) Mount(router *rtr.Router) { 
    mounter.BasePath = strings.TrimSuffix(mounter.BasePath, "/") 
    for _, route := range mounter.Routes { 
     path := route.Path 
     if !strings.HasSuffix(path, "/") { 
      path += "/" 
     } 
     path = mounter.BasePath + path 
     switch strings.ToLower(route.Method) { 
     case "get": 
      router.GET(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "post": 
      router.POST(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "delete": 
      router.DELETE(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "put": 
      router.PUT(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     } 
    } 
} 

一切正常相當不錯,如果我嘗試發送一個post請求到一個get端點,它會給出一個不錯的404,但方法工作得很好唯一的問題是它總是不分子路徑與去年添加的成員的處理響應這樣

package api 
var ApiRouter = express.NewRoutes("/api/") 

func init() { 
    ApiRouter.GET("/", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "testget/") 
    }) 
    ApiRouter.GET("/pt", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "pt") 
    }) 
    ApiRouter.POST("/test", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "test/post") 
    }) 
} 

package main 
func main() { 
    router := express.New() 
    api.ApiRouter.Mount(router) 
    for _, route := range api.ApiRouter.Routes { 
     fmt.Println(*route) 
    } 
    router.ServeFiles("/public/*filepath", http.Dir("./public/")) 
    http.ListenAndServe(":1024", router) 
} 

總是會反饋test/postrange我正在上面做的用於測試目的的輸出是 所以,你有什麼想法爲什麼它總是使用相同的功能來響應,但完全識別路徑?

回答

1

問題在於Mount方法,它被稱爲Iteration Variables and Closures。聲明一個新的變量來捕獲route

thisRoute := route //capture iteration variable 
switch strings.ToLower(route.Method) { 
case "get": 
    router.GET(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
     thisRoute.Func(res, req, params) 
    }) 
case "post": 
    router.POST(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
     thisRoute.Func(res, req, params) 
    }) 
//... 
} 
+0

哇答案解決我的問題,除了坐你分享是驚人的謝謝你:) – nikoss

相關問題