在Go语言中,可以根据字符串实例化不同的类型吗?

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

Can I instance differenct types according to string in golang?

问题

我想在Go语言中实现MVC模式。但是似乎很难实现我想要的效果。

在Testcontroller.go文件中,我有以下代码:

func (c *TestController) Test() {
    //
}

func (c *TestController) Index() {
    //
}

只有一个控制器时,我可以使用reflect.ValueOf(TestController{}).MethodByName().Call()来执行该函数。

现在我想添加另一个控制器,但是似乎我无法通过不同的字符串创建不同的实例:

controllerName := strings.Split(r.URL.Path, "/")
controller = reflect.ValueOf(controllerName[1])

我知道这是完全错误的,但我希望如果controllerName等于"Test",我可以得到一个TestController实例,如果controllerName等于"Index",我可以得到一个IndexController实例。使用反射似乎无法实现我想要的效果。有没有其他方法可以做到这一点呢?

非常感谢!

英文:

I want to implement MVC in golang. But it seems like hard to achieve what I want.
in Testcontroller.go I have:

func (c *TestController) Test() {
	//
}

func (c *TestController) Index() {
	//
}

With only a controller, I can use reflect.ValueOf(TestController{}).MethodByName().Call() to execute that function.
now I want to add another controller. but It seems like I can't new different instance by different string:

controllerName := strings.Split(r.URL.Path, "/")
controller = reflect.ValueOf(controllerName[1])

I know this is totaly wrong, but I hope I can get a TestController instance if controllerName == "Test" and get a IndexController instance if controllerName == "Index", using reflect seems can't achieve what I want. Is there any way to do is?
Thank you very much!

答案1

得分: 2

你可以这样做:

为你的控制器定义一个接口:

type Controller interface {
   // Route 返回该控制器的根路由
   Route() string
}

在控制器中实现它:

// 这告诉我们的应用程序这个控制器的路由是什么
func (c *TestController) Route() string {
    return "test"
}

func (c *TestController) Test() {
    //
}

func (c *TestController) Index() {
    //
}

在我们的应用程序中,创建一个控制器的注册表,你可以查找它们:

var controllers = make([]Controller, 0)

// 以某种方式进行注册

现在在服务过程中:

假设路径是 /<controller>/<method>

controllerName := strings.Split(r.URL.Path, "/")

// 再次,你可以在这里使用一个映射,但对于几个控制器来说可能不值得
for _, c := range controllers {
    if c.Route() == controllerName[1] {

       // 做你在单个控制器示例中所做的事情
       callControllerWithReflection(c, controllerName[2])
    }
}

希望对你有所帮助!

英文:

You could do something like that:

Define an interface for your controllers:

type Controller interface {
   // Route returns the root route for that controller
   Route() string
}

In a controller just implement it:

// this tells our app what&#39;s the route for this controller
func (c *TestController) Route() string {
    return &quot;test&quot;
}

func (c *TestController) Test() {
    //
}

func (c *TestController) Index() {
    //
}

In our app, create a registry of your controllers, and you can look them up:

var controllers = make([]Controller, 0)

// register them somehow

And now in the serving process:

// assuming the path is /&lt;controller&gt;/&lt;method&gt;
controllerName := strings.Split(r.URL.Path, &quot;/&quot;)

// again, you can use a map here, but for a few controllers it&#39;s not worth it probably
for _, c := range controllers {
    if c.Route() == controllerName[1] {

       // do what you did in the single controller example
       callControllerWithReflection(c, controllerName[2])
    }
}

huangapple
  • 本文由 发表于 2015年1月25日 16:45:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/28134710.html
匿名

发表评论

匿名网友

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

确定