地图中的函数是 <nil>
function in map is <nil>
我正在尝试在 Go 中构建一个简单的路由器,我在结构上有一个 get 方法,它应该将回调传递给以 url 作为键的 Get 路由映射,似乎 fmt.Println(urlCallback)
正在返回一个 nil 值,如果我尝试调用它会导致运行时恐慌,来自 javascript 背景有了这个,如果有人能告诉我为什么传递的 func 是 nil 那就太好了。
这是我的 "Router" 包裹。
package Router
import (
"fmt"
"net/http"
"net/url"
"log"
)
type Res http.ResponseWriter
type Req *http.Request
type RouteMap map[*url.URL]func(Res, Req)
type MethodMap map[string]RouteMap
type Router struct {
Methods MethodMap
}
func (router *Router) Get(urlString string, callback func(Res, Req)) {
parsedUrl, err := url.Parse(urlString)
if(err != nil) {
panic(err)
}
fmt.Println(parsedUrl)
router.Methods["GET"][parsedUrl] = callback
}
func (router *Router) initMaps() {
router.Methods = MethodMap{}
router.Methods["GET"] = RouteMap{}
}
func (router Router) determineHandler(res http.ResponseWriter, req *http.Request) {
fmt.Println(req.URL)
fmt.Println(req.Method)
methodMap := router.Methods[req.Method]
urlCallback := methodMap[req.URL]
fmt.Println(methodMap)
fmt.Println(urlCallback)
}
func (router Router) Serve(host string, port string) {
fullHost := host + ":" + port
fmt.Println("Router is now serving to:" + fullHost)
http.HandleFunc("/", router.determineHandler)
err := http.ListenAndServe(fullHost, nil)
if err == nil {
fmt.Println("Router is now serving to:" + fullHost)
} else {
fmt.Println("An error occurred")
log.Fatal(err)
}
}
func NewRouter() Router {
newRouter := Router{}
newRouter.initMaps()
return newRouter
}
和我的主要。
package main
import (
"./router"
"fmt"
)
func main() {
router := Router.NewRouter()
router.Get("/test", func(Router.Res, Router.Req) {
fmt.Println("In test woohooo!")
})
router.Serve("localhost", "8888")
}
您正在使用 *URL.url
个对象作为地图键。由于两个不同的对象不会相同,因此您无法再次访问该路径的密钥。很恐慌因为
urlCallback := methodMap[req.URL]
不是现有密钥,因此您正在访问 nil 值。在这种情况下,您可能想要做的是使用 URL.url
对象的 Path
属性。
所以你会:
type RouteMap map[string]func(Res, Req)
在Get()
中:
router.Methods["GET"][parsedUrl.Path] = callback
对于determineRouter()
,您可以这样做:
urlCallback, exists := methodMap[req.URL.Path]
if exists != false {
urlCallback(res, req)
}
这会在尝试调用之前添加一个检查以查看密钥是否存在。
我正在尝试在 Go 中构建一个简单的路由器,我在结构上有一个 get 方法,它应该将回调传递给以 url 作为键的 Get 路由映射,似乎 fmt.Println(urlCallback)
正在返回一个 nil 值,如果我尝试调用它会导致运行时恐慌,来自 javascript 背景有了这个,如果有人能告诉我为什么传递的 func 是 nil 那就太好了。
这是我的 "Router" 包裹。
package Router
import (
"fmt"
"net/http"
"net/url"
"log"
)
type Res http.ResponseWriter
type Req *http.Request
type RouteMap map[*url.URL]func(Res, Req)
type MethodMap map[string]RouteMap
type Router struct {
Methods MethodMap
}
func (router *Router) Get(urlString string, callback func(Res, Req)) {
parsedUrl, err := url.Parse(urlString)
if(err != nil) {
panic(err)
}
fmt.Println(parsedUrl)
router.Methods["GET"][parsedUrl] = callback
}
func (router *Router) initMaps() {
router.Methods = MethodMap{}
router.Methods["GET"] = RouteMap{}
}
func (router Router) determineHandler(res http.ResponseWriter, req *http.Request) {
fmt.Println(req.URL)
fmt.Println(req.Method)
methodMap := router.Methods[req.Method]
urlCallback := methodMap[req.URL]
fmt.Println(methodMap)
fmt.Println(urlCallback)
}
func (router Router) Serve(host string, port string) {
fullHost := host + ":" + port
fmt.Println("Router is now serving to:" + fullHost)
http.HandleFunc("/", router.determineHandler)
err := http.ListenAndServe(fullHost, nil)
if err == nil {
fmt.Println("Router is now serving to:" + fullHost)
} else {
fmt.Println("An error occurred")
log.Fatal(err)
}
}
func NewRouter() Router {
newRouter := Router{}
newRouter.initMaps()
return newRouter
}
和我的主要。
package main
import (
"./router"
"fmt"
)
func main() {
router := Router.NewRouter()
router.Get("/test", func(Router.Res, Router.Req) {
fmt.Println("In test woohooo!")
})
router.Serve("localhost", "8888")
}
您正在使用 *URL.url
个对象作为地图键。由于两个不同的对象不会相同,因此您无法再次访问该路径的密钥。很恐慌因为
urlCallback := methodMap[req.URL]
不是现有密钥,因此您正在访问 nil 值。在这种情况下,您可能想要做的是使用 URL.url
对象的 Path
属性。
所以你会:
type RouteMap map[string]func(Res, Req)
在Get()
中:
router.Methods["GET"][parsedUrl.Path] = callback
对于determineRouter()
,您可以这样做:
urlCallback, exists := methodMap[req.URL.Path]
if exists != false {
urlCallback(res, req)
}
这会在尝试调用之前添加一个检查以查看密钥是否存在。