英文:
Call func at memory address
问题
我有一个以结构体为键、函数为值的映射表,当我根据给定的键检索值时,我想调用这个函数。
map[struct]func
map[
{contact %!s(int=1)}:%!s(main.Controller=0x4c7b50)
{services/basket %!s(int=2)}:%!s(main.Controller=0x4c7ad0)
{categories %!s(int=1)}:%!s(main.Controller=0x4c7ae0)
{categories/{category} %!s(int=2)}:%!s(main.Controller=0x4c7af0)
{categories/{category}/{product} %!s(int=3)}:%!s(main.Controller=0x4c7b00)
{basket %!s(int=1)}:%!s(main.Controller=0x4c7b10)
{checkout %!s(int=1)}:%!s(main.Controller=0x4c7b40)
{sitemap %!s(int=1)}:%!s(main.Controller=0x4c7b30)
{services/order %!s(int=2)}:%!s(main.Controller=0x4c7ac0)
{services/image %!s(int=2)}:%!s(main.Controller=0x4c7b20)
{/ %!s(int=1)}:%!s(main.Controller=0x4c7a00)
]
c := RouteMap[struct]
如果我使用fmt.Printf("%s", c)
,我会得到内存地址,如何调用该地址上的函数?
我尝试了c()
,但是会导致运行时错误:
%s
0x4c7b10%s
<nil>panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x4c76f4]
goroutine 5 [running]:
main.RequestHandler(0x577ce0, 0xc042004018)
C:/Users/mon/Desktop/server.go:91 +0x684
created by main.main
C:/Users/mon/Desktop/server.go:41 +0x2a0
示例代码:
package main
import (
"bufio"
"bytes"
"fmt"
"net"
"strings"
"time"
)
var RouteMap = make(map[PathIdentifier]Controller)
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// 处理错误
}
MapRoute("/", HomeController)
MapRoute("categories", CategoriesController)
MapRoute("categories/{category}", CategoryController)
MapRoute("categories/{category}/{product}", CategoryProductController)
MapRoute("basket", BasketController)
MapRoute("checkout", CheckoutController)
MapRoute("sitemap", SitemapController)
MapRoute("contact", ContactController)
MapRoute("services/order", OrderServiceController)
MapRoute("services/basket", BasketServiceController)
MapRoute("services/image", ImageServiceController)
fmt.Printf("%s\n", RouteMap)
for {
conn, err := ln.Accept()
if err != nil {
// 处理错误
}
go RequestHandler(conn)
}
}
// ----------------------- 请求和响应 ---------------------------
func ParseQueryString() {}
func ParsePostData() {}
func ResponseHeaders() {}
func ParseRequestHeaders() {}
func RequestHandler(conn net.Conn) {
CrLf := "\r\n"
Terminator := CrLf + CrLf
defer func() {
//fmt.Println("Closing connection...")
conn.Close()
}()
timeoutDuration := 10 * time.Second
bufReader := bufio.NewReader(conn)
conn.SetReadDeadline(time.Now().Add(timeoutDuration))
requestBytes, err := bufReader.ReadBytes('\n')
if err != nil {
fmt.Println(err)
return
}
requestTokens := bytes.Split(requestBytes, []byte(" "))
requestMethod := string(requestTokens[0])
requestPath := string(requestTokens[1])
//requestHTTPVersion := string(requestTokens[2])
if requestMethod == "GET" {
// 解析路径
pathTokens := strings.Split(requestPath, "/")
segments := len(pathTokens)
key := PathIdentifier{path: "categories/{category}/{product}", segments: (segments - 1)}
c := RouteMap[key]
fmt.Print("%s\n", c)
}
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)
conn.Write(document)
}
// ----------------------------- 控制器 -----------------------------
type Controller func()
type PathIdentifier struct {
path string
segments int
}
func MapRoute(view string, controller Controller) {
if controller != nil {
if view != "/" {
pathTokens := strings.Split(view, "/")
key := PathIdentifier{path: view, segments: len(pathTokens)}
RouteMap[key] = controller
return
}
key := PathIdentifier{path: view, segments: 1}
RouteMap[key] = controller
}
}
func HomeController() {
fmt.Print("调用 HomeController。\n")
}
func OrderServiceController() {
}
func BasketServiceController() {
}
func CategoriesController() {
}
func CategoryController() {
}
func CategoryProductsController() {
}
func CategoryProductController() {
}
func BasketController() {
}
func ImageServiceController() {
}
func SitemapController() {
}
func CheckoutController() {
}
func ContactController() {
}
以上是你要翻译的内容。
英文:
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
map[struct]func
map[
{contact %!s(int=1)}:%!s(main.Controller=0x4c7b50)
{services/basket %!s(int=2)}:%!s(main.Controller=0x4c7ad0)
{categories %!s(int=1)}:%!s(main.Controller=0x4c7ae0)
{categories/{category} %!s(int=2)}:%!s(main.Controller=0x4c7af0)
{categories/{category}/{product} %!s(int=3)}:%!s(main.Controller=0x4c7b00)
{basket %!s(int=1)}:%!s(main.Controller=0x4c7b10)
{checkout %!s(int=1)}:%!s(main.Controller=0x4c7b40)
{sitemap %!s(int=1)}:%!s(main.Controller=0x4c7b30)
{services/order %!s(int=2)}:%!s(main.Controller=0x4c7ac0)
{services/image %!s(int=2)}:%!s(main.Controller=0x4c7b20)
{/ %!s(int=1)}:%!s(main.Controller=0x4c7a00)
]
c := RouteMap[struct]
If I fmt.Printf("%s", 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:
%s
0x4c7b10%s
<nil>panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x4c76f4]
goroutine 5 [running]:
main.RequestHandler(0x577ce0, 0xc042004018)
C:/Users/mon/Desktop/server.go:91 +0x684
created by main.main
C:/Users/mon/Desktop/server.go:41 +0x2a0
EXAMPLE
package main
import (
"bufio"
"bytes"
"fmt"
"net"
"strings"
"time"
)
var RouteMap = make(map[PathIdentifier]Controller)
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
MapRoute("/", HomeController)
MapRoute("categories", CategoriesController)
MapRoute("categories/{category}", CategoryController)
MapRoute("categories/{category}/{product}", CategoryProductController)
MapRoute("basket", BasketController)
MapRoute("checkout", CheckoutController)
MapRoute("sitemap", SitemapController)
MapRoute("contact", ContactController)
MapRoute("services/order", OrderServiceController)
MapRoute("services/basket", BasketServiceController)
MapRoute("services/image", ImageServiceController)
fmt.Printf("%s\n", RouteMap)
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go RequestHandler(conn)
}
}
// ----------------------- Request & Response ---------------------------
func ParseQueryString() {}
func ParsePostData() {}
func ResponseHeaders() {}
func ParseRequestHeaders() {}
func RequestHandler(conn net.Conn) {
CrLf := "\r\n"
Terminator := CrLf + CrLf
defer func() {
//fmt.Println("Closing connection...")
conn.Close()
}()
timeoutDuration := 10 * time.Second
bufReader := bufio.NewReader(conn)
conn.SetReadDeadline(time.Now().Add(timeoutDuration))
requestBytes, err := bufReader.ReadBytes('\n')
if err != nil {
fmt.Println(err)
return
}
requestTokens := bytes.Split(requestBytes, []byte(" "))
requestMethod := string(requestTokens[0])
requestPath := string(requestTokens[1])
//requestHTTPVersion := string(requestTokens[2])
if requestMethod == "GET" {
// Parse path
pathTokens := strings.Split(requestPath, "/")
segments := len(pathTokens)
key := PathIdentifier{path: "categories/{category}/{product}", segments: (segments - 1)}
c := RouteMap[key]
fmt.Print("%s\n", c)
}
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)
conn.Write(document)
}
// ----------------------------- Controller -----------------------------
type Controller func()
type PathIdentifier struct {
path string
segments int
}
func MapRoute(view string, controller Controller) {
if controller != nil {
if view != "/" {
pathTokens := strings.Split(view, "/")
key := PathIdentifier{path: view, segments: len(pathTokens)}
RouteMap[key] = controller
return
}
key := PathIdentifier{path: view, segments: 1}
RouteMap[key] = controller
}
}
func HomeController() {
fmt.Print("Invoking the HomeController.\n")
}
func OrderServiceController() {
}
func BasketServiceController() {
}
func CategoriesController() {
}
func CategoryController() {
}
func CategoryProductsController() {
}
func CategoryProductController() {
}
func BasketController() {
}
func ImageServiceController() {
}
func SitemapController() {
}
func CheckoutController() {
}
func ContactController() {
}
答案1
得分: 1
我不确定你需要称之为“按地址调用”。当你通过将其作为变量传递来调用时,编译器会在幕后为你完成这个操作。它会获取其地址并调用它。
如果你希望有一定程度的间接性,你可以这样做:
M := map[string]func()
M["function 1"] = F
// 然后可以通过 map 来调用它们
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:
M := map[string]func()
M["function 1"] = F
// and then call them from map like
M["function 1"]()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论