【问题标题】:make a instance of a struct by string通过字符串创建结构的实例
【发布时间】:2014-09-06 16:13:03
【问题描述】:

我正在构建一个应用程序,我想在其中使用一个简单的 mvc 模型

我有一个包控制器,里面有这样的控制器结构

type UserController struct {}

func (u *UserController) Index(res http.ResponseWriter, req http.Request) {
  // some code in it
}

我想要实现的是我可以通过字符串来创建该控制器的实例

func NewAppController("user") { }

所以我可以通过路由请求动态创建控制器实例

我想到的另一种方法是像这样映射我的控制器

var controllerProvider = map[string]interface{} {
   "user": &controllers.UserController{},
   "warehouse": &controllers.WarehouseController{},
 }

然后调用它

appController = mux.Vars(req)["controller"]
c := controllerProvider[appController]

但我宁愿使用第一种方法,知道如何处理这个问题吗?

【问题讨论】:

标签: go


【解决方案1】:

如果你使用这个:

var controllerProvider = map[string]interface{} {
   "user": &controllers.UserController{},
   "warehouse": &controllers.WarehouseController{},
}

请注意,这些不是每次访问的新实例。如果你多次使用controllerProvider,它总是会返回指向只初始化一次的实例的指针。

您可能希望使用函数来动态生成实例:

var controllerProvider = map[string]func() interface{}{
    "user":      func() interface{} { return &controllers.UserController{} },
    "warehouse": func() interface{} { return &controllers.WarehouseController{} },
}

c := controllerProvider[appController]()

【讨论】:

    【解决方案2】:

    您可以尝试创建一个实现reflect.Type 接口的新对象,然后通过reflect 的机制使用它,但这看起来完全是浪费时间。相反,请考虑以下替代方案:

    • 使用Name stringMethods map[string]ActionFunc 等字段创建结构。这会起作用,但对我来说它看起来不是很地道。 (如果有的话,这让人想起一些 JavaScript OOP 实现。)

    • 使用框架。如果您对 MVC 感到满意,为什么不使用已经存在的 Go 的 MVC 框架之一呢? Beego 和 Revel 浮现在脑海中。

    • 重新考虑您的架构。从我现在看到的情况来看,您正在尝试像编写 Ruby-on-Rails 一样编写 Go。围棋不一样。从 vanilla net/http 开始,并为您的应用创建一个最小实现。那是你的原型。有了这个原型,你就可以重写和扩展它。想要资源丰富的路线?添加gorilla/mux 或其他选择的路由器。需要数据存储?添加一个 ORM。想要更多的可测试性和灵活性?接口,无处不在的接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-04
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 2016-09-14
      • 1970-01-01
      相关资源
      最近更新 更多