Go语言 如何从变量中的字符串调用函数?

lf3rwulv  于 12个月前  发布在  Go
关注(0)|答案(2)|浏览(153)

我正在使用Go Fiber构建小型API

package main

import (
    "fmt"

    "github.com/gofiber/fiber/v2"
    _ "github.com/serhioromano/mygotest/pkg/products"
    _ "github.com/serhioromano/mygotest/pkg/users"
)

func main(){
    app := fiber. New(fiber.Config{
        ServerHeader: "Sergey API",
    });

    app.Post("/api/v1/:pkg/:function", func(c *fiber.Ctx) error {
        return c.SendString("123");
    })

    app.Listen(":3000")
}

现在在我的端点内我想

app.Post("/api/v1/:pkg/:function", func(c *fiber.Ctx) error {
    // For URL http://localhost:3000/api/v1/products/add
    return products.Add(&c);
    // For URL http://localhost:3000/api/v1/users/list
    return users. List(&c);
})

如何调用这些函数?

q3aa0525

q3aa05251#

这是一个简单的方法来实现你想要的东西:

import (
  "github.com/gofiber/fiber/v2"

  "github.com/serhioromano/mygotest/pkg/products" 
  "github.com/serhioromano/mygotest/pkg/users"
)

func main() {

  app := fiber.New()

  app.Post("/api/v1/:pkg/:func", func(c *fiber.Ctx) error {

    pkgName := c.Params("pkg")
    funcName := c.Params("func")

    switch pkgName {
      case "products":
        return products.Invoke(funcName, c)
      
      case "users":  
        return users.Invoke(funcName, c)
    }

    return fiber.ErrNotFound
  })

}

// products/users pkg

func Invoke(name string, c *fiber.Ctx) error {
  
  switch name {
    case "add":
      return Add(c)
    
    case "list":
      return List(c) 
  }

  return fiber.ErrNotFound

}

关键步骤是:
从URL参数中获取包和函数名称在每个包中有一个公共的Invoke函数打开函数名称并调用实际的包函数这避免了包和主应用之间的紧密耦合。

ojsjcaue

ojsjcaue2#

您是对的,我前面提供的动态分派解决方案仍然需要在每次添加新函数时向中央Invoke方法添加新的案例。为了实现您所希望的-自动注册新的处理程序而无需任何额外的连接-您可以使用反射。
下面是一种使用反射实现自动注册和调用处理程序的方法:
1.在单独的文件中定义处理程序函数,例如:

// products/add.go

func Add(c *fiber.Ctx) error {
  // handler logic
  return c.SendString("Added product") 
}

1.使用init()函数注册处理程序:

// products/add.go

func init() {
  registry.Register("products/add", Add) 
}

1.注册表可以将字符串键Map到处理程序函数:

var registry = map[string]HandlerFunc{} 

type HandlerFunc func(*fiber.Ctx) error

func (r *Registry) Register(key string, fn HandlerFunc) {
  registry[key] = fn
}

1.然后在主路由中,查找并调用处理程序:

app.Post("/api/:key", func(c *fiber.Ctx) {
  key := c.Params("key")
  if handler := registry[key]; handler != nil {
    handler(c)
  }
})

这允许在任何文件中添加新的处理程序,并在init上自动注册,而无需修改现有代码。关键概念是反射函数和init函数。

相关问题