英文:
function in map is <nil>
问题
我正在尝试在Go语言中构建一个简单的路由器。我在一个结构体上有一个get方法,应该将回调传递给Get路由映射,其中URL作为键。似乎fmt.Println(urlCallback)
返回了一个空值,并且如果我尝试调用它,会导致运行时恐慌。作为一个来自JavaScript背景的人,我刚刚开始理解指针等内容,并且觉得可能与此有关。如果有人能告诉我为什么传递的函数是空值,那就太好了。
这是我的"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
}
这是我的main函数:
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")
}
英文:
I am trying to build a simple router in Go, I have a get method on a struct that should be passing a callback to the Get route map with the url as the key, it seems that fmt.Println(urlCallback)
is returning a nil value and causes a runtime panic if i tried to call it, coming from a javascript background I am only just coming to grips with pointers and the like and feel it may have something to do with this,if someone could tell me why the passed func is nil that would be great.
Here is my "Router" package.
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
}
and my main.
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")
}
答案1
得分: 6
你正在使用*URL.url
对象作为映射键。由于两个不同的对象不会相同,所以你无法再次访问该路径的键。它会出现错误,因为
urlCallback := methodMap[req.URL]
不是一个现有的键,所以你正在访问一个空值。在这种情况下,你可能想要使用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)
}
这样在调用之前会检查键是否存在。
英文:
You are using *URL.url
objects for map keys. Since two different objects won't be the same, you can't access the key for that path again. It's panicking because
urlCallback := methodMap[req.URL]
isn't an existing key, and so you're accessing a nil value. What you probably want to do in this case is use the Path
property of the URL.url
object.
So you'd have:
type RouteMap map[string]func(Res, Req)
In Get()
:
router.Methods["GET"][parsedUrl.Path] = callback
For determineRouter()
, you can do this:
urlCallback, exists := methodMap[req.URL.Path]
if exists != false {
urlCallback(res, req)
}
This adds a check to see if the key exists before it tries to call it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论