调用函数位于内存地址的func。

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

Call func at memory address

问题

我有一个以结构体为键、函数为值的映射表,当我根据给定的键检索值时,我想调用这个函数。

  1. map[struct]func
  2. map[
  3. {contact %!s(int=1)}:%!s(main.Controller=0x4c7b50)
  4. {services/basket %!s(int=2)}:%!s(main.Controller=0x4c7ad0)
  5. {categories %!s(int=1)}:%!s(main.Controller=0x4c7ae0)
  6. {categories/{category} %!s(int=2)}:%!s(main.Controller=0x4c7af0)
  7. {categories/{category}/{product} %!s(int=3)}:%!s(main.Controller=0x4c7b00)
  8. {basket %!s(int=1)}:%!s(main.Controller=0x4c7b10)
  9. {checkout %!s(int=1)}:%!s(main.Controller=0x4c7b40)
  10. {sitemap %!s(int=1)}:%!s(main.Controller=0x4c7b30)
  11. {services/order %!s(int=2)}:%!s(main.Controller=0x4c7ac0)
  12. {services/image %!s(int=2)}:%!s(main.Controller=0x4c7b20)
  13. {/ %!s(int=1)}:%!s(main.Controller=0x4c7a00)
  14. ]
  15. c := RouteMap[struct]

如果我使用fmt.Printf("%s", c),我会得到内存地址,如何调用该地址上的函数?

我尝试了c(),但是会导致运行时错误:

  1. %s
  2. 0x4c7b10%s
  3. <nil>panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xc0000005 code=0x0 addr=0x0 pc=0x4c76f4]
  5. goroutine 5 [running]:
  6. main.RequestHandler(0x577ce0, 0xc042004018)
  7. C:/Users/mon/Desktop/server.go:91 +0x684
  8. created by main.main
  9. C:/Users/mon/Desktop/server.go:41 +0x2a0

示例代码:

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "net"
  7. "strings"
  8. "time"
  9. )
  10. var RouteMap = make(map[PathIdentifier]Controller)
  11. func main() {
  12. ln, err := net.Listen("tcp", ":8080")
  13. if err != nil {
  14. // 处理错误
  15. }
  16. MapRoute("/", HomeController)
  17. MapRoute("categories", CategoriesController)
  18. MapRoute("categories/{category}", CategoryController)
  19. MapRoute("categories/{category}/{product}", CategoryProductController)
  20. MapRoute("basket", BasketController)
  21. MapRoute("checkout", CheckoutController)
  22. MapRoute("sitemap", SitemapController)
  23. MapRoute("contact", ContactController)
  24. MapRoute("services/order", OrderServiceController)
  25. MapRoute("services/basket", BasketServiceController)
  26. MapRoute("services/image", ImageServiceController)
  27. fmt.Printf("%s\n", RouteMap)
  28. for {
  29. conn, err := ln.Accept()
  30. if err != nil {
  31. // 处理错误
  32. }
  33. go RequestHandler(conn)
  34. }
  35. }
  36. // ----------------------- 请求和响应 ---------------------------
  37. func ParseQueryString() {}
  38. func ParsePostData() {}
  39. func ResponseHeaders() {}
  40. func ParseRequestHeaders() {}
  41. func RequestHandler(conn net.Conn) {
  42. CrLf := "\r\n"
  43. Terminator := CrLf + CrLf
  44. defer func() {
  45. //fmt.Println("Closing connection...")
  46. conn.Close()
  47. }()
  48. timeoutDuration := 10 * time.Second
  49. bufReader := bufio.NewReader(conn)
  50. conn.SetReadDeadline(time.Now().Add(timeoutDuration))
  51. requestBytes, err := bufReader.ReadBytes('\n')
  52. if err != nil {
  53. fmt.Println(err)
  54. return
  55. }
  56. requestTokens := bytes.Split(requestBytes, []byte(" "))
  57. requestMethod := string(requestTokens[0])
  58. requestPath := string(requestTokens[1])
  59. //requestHTTPVersion := string(requestTokens[2])
  60. if requestMethod == "GET" {
  61. // 解析路径
  62. pathTokens := strings.Split(requestPath, "/")
  63. segments := len(pathTokens)
  64. key := PathIdentifier{path: "categories/{category}/{product}", segments: (segments - 1)}
  65. c := RouteMap[key]
  66. fmt.Print("%s\n", c)
  67. }
  68. document := []byte("HTTP/1.1 200 OK" + CrLf + "Date: Mon, 27 Jul 2009 12:28:53 GMT" + CrLf + "Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT" + CrLf + "Content-Length: 49" + CrLf + "Content-Type: text/html" + CrLf + "Connection: Closed" + Terminator + "<html><body><h1>Hello, World!</h1></body></html>" + Terminator)
  69. conn.Write(document)
  70. }
  71. // ----------------------------- 控制器 -----------------------------
  72. type Controller func()
  73. type PathIdentifier struct {
  74. path string
  75. segments int
  76. }
  77. func MapRoute(view string, controller Controller) {
  78. if controller != nil {
  79. if view != "/" {
  80. pathTokens := strings.Split(view, "/")
  81. key := PathIdentifier{path: view, segments: len(pathTokens)}
  82. RouteMap[key] = controller
  83. return
  84. }
  85. key := PathIdentifier{path: view, segments: 1}
  86. RouteMap[key] = controller
  87. }
  88. }
  89. func HomeController() {
  90. fmt.Print("调用 HomeController。\n")
  91. }
  92. func OrderServiceController() {
  93. }
  94. func BasketServiceController() {
  95. }
  96. func CategoriesController() {
  97. }
  98. func CategoryController() {
  99. }
  100. func CategoryProductsController() {
  101. }
  102. func CategoryProductController() {
  103. }
  104. func BasketController() {
  105. }
  106. func ImageServiceController() {
  107. }
  108. func SitemapController() {
  109. }
  110. func CheckoutController() {
  111. }
  112. func ContactController() {
  113. }

以上是你要翻译的内容。

英文:

I have a map with a struct as key and a func as value, I would like to call the func when I retrieve the value for a given key

  1. map[struct]func
  2. map[
  3. {contact %!s(int=1)}:%!s(main.Controller=0x4c7b50)
  4. {services/basket %!s(int=2)}:%!s(main.Controller=0x4c7ad0)
  5. {categories %!s(int=1)}:%!s(main.Controller=0x4c7ae0)
  6. {categories/{category} %!s(int=2)}:%!s(main.Controller=0x4c7af0)
  7. {categories/{category}/{product} %!s(int=3)}:%!s(main.Controller=0x4c7b00)
  8. {basket %!s(int=1)}:%!s(main.Controller=0x4c7b10)
  9. {checkout %!s(int=1)}:%!s(main.Controller=0x4c7b40)
  10. {sitemap %!s(int=1)}:%!s(main.Controller=0x4c7b30)
  11. {services/order %!s(int=2)}:%!s(main.Controller=0x4c7ac0)
  12. {services/image %!s(int=2)}:%!s(main.Controller=0x4c7b20)
  13. {/ %!s(int=1)}:%!s(main.Controller=0x4c7a00)
  14. ]
  15. c := RouteMap[struct]

If I fmt.Printf(&quot;%s&quot;, c) I get the memory address, how do I invoke the func at the address?

I have tried c() but that gives a runtime error:

  1. %s
  2. 0x4c7b10%s
  3. &lt;nil&gt;panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xc0000005 code=0x0 addr=0x0 pc=0x4c76f4]
  5. goroutine 5 [running]:
  6. main.RequestHandler(0x577ce0, 0xc042004018)
  7. C:/Users/mon/Desktop/server.go:91 +0x684
  8. created by main.main
  9. C:/Users/mon/Desktop/server.go:41 +0x2a0

EXAMPLE

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;bytes&quot;
  5. &quot;fmt&quot;
  6. &quot;net&quot;
  7. &quot;strings&quot;
  8. &quot;time&quot;
  9. )
  10. var RouteMap = make(map[PathIdentifier]Controller)
  11. func main() {
  12. ln, err := net.Listen(&quot;tcp&quot;, &quot;:8080&quot;)
  13. if err != nil {
  14. // handle error
  15. }
  16. MapRoute(&quot;/&quot;, HomeController)
  17. MapRoute(&quot;categories&quot;, CategoriesController)
  18. MapRoute(&quot;categories/{category}&quot;, CategoryController)
  19. MapRoute(&quot;categories/{category}/{product}&quot;, CategoryProductController)
  20. MapRoute(&quot;basket&quot;, BasketController)
  21. MapRoute(&quot;checkout&quot;, CheckoutController)
  22. MapRoute(&quot;sitemap&quot;, SitemapController)
  23. MapRoute(&quot;contact&quot;, ContactController)
  24. MapRoute(&quot;services/order&quot;, OrderServiceController)
  25. MapRoute(&quot;services/basket&quot;, BasketServiceController)
  26. MapRoute(&quot;services/image&quot;, ImageServiceController)
  27. fmt.Printf(&quot;%s\n&quot;, RouteMap)
  28. for {
  29. conn, err := ln.Accept()
  30. if err != nil {
  31. // handle error
  32. }
  33. go RequestHandler(conn)
  34. }
  35. }
  36. // ----------------------- Request &amp; Response ---------------------------
  37. func ParseQueryString() {}
  38. func ParsePostData() {}
  39. func ResponseHeaders() {}
  40. func ParseRequestHeaders() {}
  41. func RequestHandler(conn net.Conn) {
  42. CrLf := &quot;\r\n&quot;
  43. Terminator := CrLf + CrLf
  44. defer func() {
  45. //fmt.Println(&quot;Closing connection...&quot;)
  46. conn.Close()
  47. }()
  48. timeoutDuration := 10 * time.Second
  49. bufReader := bufio.NewReader(conn)
  50. conn.SetReadDeadline(time.Now().Add(timeoutDuration))
  51. requestBytes, err := bufReader.ReadBytes(&#39;\n&#39;)
  52. if err != nil {
  53. fmt.Println(err)
  54. return
  55. }
  56. requestTokens := bytes.Split(requestBytes, []byte(&quot; &quot;))
  57. requestMethod := string(requestTokens[0])
  58. requestPath := string(requestTokens[1])
  59. //requestHTTPVersion := string(requestTokens[2])
  60. if requestMethod == &quot;GET&quot; {
  61. // Parse path
  62. pathTokens := strings.Split(requestPath, &quot;/&quot;)
  63. segments := len(pathTokens)
  64. key := PathIdentifier{path: &quot;categories/{category}/{product}&quot;, segments: (segments - 1)}
  65. c := RouteMap[key]
  66. fmt.Print(&quot;%s\n&quot;, c)
  67. }
  68. document := []byte(&quot;HTTP/1.1 200 OK&quot; + CrLf + &quot;Date: Mon, 27 Jul 2009 12:28:53 GMT&quot; + CrLf + &quot;Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT&quot; + CrLf + &quot;Content-Length: 49&quot; + CrLf + &quot;Content-Type: text/html&quot; + CrLf + &quot;Connection: Closed&quot; + Terminator + &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Hello, World!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&quot; + Terminator)
  69. conn.Write(document)
  70. }
  71. // ----------------------------- Controller -----------------------------
  72. type Controller func()
  73. type PathIdentifier struct {
  74. path string
  75. segments int
  76. }
  77. func MapRoute(view string, controller Controller) {
  78. if controller != nil {
  79. if view != &quot;/&quot; {
  80. pathTokens := strings.Split(view, &quot;/&quot;)
  81. key := PathIdentifier{path: view, segments: len(pathTokens)}
  82. RouteMap[key] = controller
  83. return
  84. }
  85. key := PathIdentifier{path: view, segments: 1}
  86. RouteMap[key] = controller
  87. }
  88. }
  89. func HomeController() {
  90. fmt.Print(&quot;Invoking the HomeController.\n&quot;)
  91. }
  92. func OrderServiceController() {
  93. }
  94. func BasketServiceController() {
  95. }
  96. func CategoriesController() {
  97. }
  98. func CategoryController() {
  99. }
  100. func CategoryProductsController() {
  101. }
  102. func CategoryProductController() {
  103. }
  104. func BasketController() {
  105. }
  106. func ImageServiceController() {
  107. }
  108. func SitemapController() {
  109. }
  110. func CheckoutController() {
  111. }
  112. func ContactController() {
  113. }

答案1

得分: 1

我不确定你需要称之为“按地址调用”。当你通过将其作为变量传递来调用时,编译器会在幕后为你完成这个操作。它会获取其地址并调用它。

如果你希望有一定程度的间接性,你可以这样做:

  1. M := map[string]func()
  2. M["function 1"] = F
  3. // 然后可以通过 map 来调用它们
  4. M["function 1"]()
英文:

I'm not sure you need to call it "by address". When you call by passing it as a variable, compiler does this for you "under-the-hood". Takes its address and calls it.

If you wish some level of indirection, you can make:

  1. M := map[string]func()
  2. M[&quot;function 1&quot;] = F
  3. // and then call them from map like
  4. M[&quot;function 1&quot;]()

huangapple
  • 本文由 发表于 2017年4月12日 00:48:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/43351857.html
匿名

发表评论

匿名网友

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

确定