在地图中的函数是<nil>。

huangapple go评论117阅读模式
英文:

function in map is <nil>

问题

我正在尝试在Go语言中构建一个简单的路由器。我在一个结构体上有一个get方法,应该将回调传递给Get路由映射,其中URL作为键。似乎fmt.Println(urlCallback)返回了一个空值,并且如果我尝试调用它,会导致运行时恐慌。作为一个来自JavaScript背景的人,我刚刚开始理解指针等内容,并且觉得可能与此有关。如果有人能告诉我为什么传递的函数是空值,那就太好了。

这是我的"Router"包:

  1. package Router
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "log"
  7. )
  8. type Res http.ResponseWriter
  9. type Req *http.Request
  10. type RouteMap map[*url.URL]func(Res, Req)
  11. type MethodMap map[string]RouteMap
  12. type Router struct {
  13. Methods MethodMap
  14. }
  15. func (router *Router) Get(urlString string, callback func(Res, Req)) {
  16. parsedUrl, err := url.Parse(urlString)
  17. if(err != nil) {
  18. panic(err)
  19. }
  20. fmt.Println(parsedUrl)
  21. router.Methods["GET"][parsedUrl] = callback
  22. }
  23. func (router *Router) initMaps() {
  24. router.Methods = MethodMap{}
  25. router.Methods["GET"] = RouteMap{}
  26. }
  27. func (router Router) determineHandler(res http.ResponseWriter, req *http.Request) {
  28. fmt.Println(req.URL)
  29. fmt.Println(req.Method)
  30. methodMap := router.Methods[req.Method]
  31. urlCallback := methodMap[req.URL]
  32. fmt.Println(methodMap)
  33. fmt.Println(urlCallback)
  34. }
  35. func (router Router) Serve(host string, port string) {
  36. fullHost := host + ":" + port
  37. fmt.Println("Router is now serving to:" + fullHost)
  38. http.HandleFunc("/", router.determineHandler)
  39. err := http.ListenAndServe(fullHost, nil)
  40. if err == nil {
  41. fmt.Println("Router is now serving to:" + fullHost)
  42. } else {
  43. fmt.Println("An error occurred")
  44. log.Fatal(err)
  45. }
  46. }
  47. func NewRouter() Router {
  48. newRouter := Router{}
  49. newRouter.initMaps()
  50. return newRouter
  51. }

这是我的main函数:

  1. package main
  2. import (
  3. "./router"
  4. "fmt"
  5. )
  6. func main() {
  7. router := Router.NewRouter()
  8. router.Get("/test", func(Router.Res, Router.Req) {
  9. fmt.Println("In test woohooo!")
  10. })
  11. router.Serve("localhost", "8888")
  12. }
英文:

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.

  1. package Router
  2. import (
  3. &quot;fmt&quot;
  4. &quot;net/http&quot;
  5. &quot;net/url&quot;
  6. &quot;log&quot;
  7. )
  8. type Res http.ResponseWriter
  9. type Req *http.Request
  10. type RouteMap map[*url.URL]func(Res, Req)
  11. type MethodMap map[string]RouteMap
  12. type Router struct {
  13. Methods MethodMap
  14. }
  15. func (router *Router) Get(urlString string, callback func(Res, Req)) {
  16. parsedUrl, err := url.Parse(urlString)
  17. if(err != nil) {
  18. panic(err)
  19. }
  20. fmt.Println(parsedUrl)
  21. router.Methods[&quot;GET&quot;][parsedUrl] = callback
  22. }
  23. func (router *Router) initMaps() {
  24. router.Methods = MethodMap{}
  25. router.Methods[&quot;GET&quot;] = RouteMap{}
  26. }
  27. func (router Router) determineHandler(res http.ResponseWriter, req *http.Request) {
  28. fmt.Println(req.URL)
  29. fmt.Println(req.Method)
  30. methodMap := router.Methods[req.Method]
  31. urlCallback := methodMap[req.URL]
  32. fmt.Println(methodMap)
  33. fmt.Println(urlCallback)
  34. }
  35. func (router Router) Serve(host string, port string) {
  36. fullHost := host + &quot;:&quot; + port
  37. fmt.Println(&quot;Router is now serving to:&quot; + fullHost)
  38. http.HandleFunc(&quot;/&quot;, router.determineHandler)
  39. err := http.ListenAndServe(fullHost, nil)
  40. if err == nil {
  41. fmt.Println(&quot;Router is now serving to:&quot; + fullHost)
  42. } else {
  43. fmt.Println(&quot;An error occurred&quot;)
  44. log.Fatal(err)
  45. }
  46. }
  47. func NewRouter() Router {
  48. newRouter := Router{}
  49. newRouter.initMaps()
  50. return newRouter
  51. }

and my main.

  1. package main
  2. import (
  3. &quot;./router&quot;
  4. &quot;fmt&quot;
  5. )
  6. func main() {
  7. router := Router.NewRouter()
  8. router.Get(&quot;/test&quot;, func(Router.Res, Router.Req) {
  9. fmt.Println(&quot;In test woohooo!&quot;)
  10. })
  11. router.Serve(&quot;localhost&quot;, &quot;8888&quot;)
  12. }

答案1

得分: 6

你正在使用*URL.url对象作为映射键。由于两个不同的对象不会相同,所以你无法再次访问该路径的键。它会出现错误,因为

  1. urlCallback := methodMap[req.URL]

不是一个现有的键,所以你正在访问一个空值。在这种情况下,你可能想要使用URL.url对象的Path属性。

所以你可以这样写:

  1. type RouteMap map[string]func(Res, Req)

Get()函数中:

  1. router.Methods["GET"][parsedUrl.Path] = callback

对于determineRouter()函数,你可以这样做:

  1. urlCallback, exists := methodMap[req.URL.Path]
  2. if exists != false {
  3. urlCallback(res, req)
  4. }

这样在调用之前会检查键是否存在。

英文:

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

  1. 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:

  1. type RouteMap map[string]func(Res, Req)

In Get():

  1. router.Methods[&quot;GET&quot;][parsedUrl.Path] = callback

For determineRouter(), you can do this:

  1. urlCallback, exists := methodMap[req.URL.Path]
  2. if exists != false {
  3. urlCallback(res, req)
  4. }

This adds a check to see if the key exists before it tries to call it.

huangapple
  • 本文由 发表于 2015年1月10日 11:59:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/27872735.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定