繁体   English   中英

前往:反思catch22反思套餐

[英]Go: Reflection catch22 reflect package

好的,我已经或正在编写一个名为mao的Web框架程序包。

我想在控制器中定义我的路线。

在毛

type (
    Controller struct {
        Route Route
    }
    Route struct {
        Name, Host, Path, Method string
    }
)

在毛进口包中

控制器/ default.go

type DefaultController struct {
    mao.Controller
}
func (this *DefaultController) Index() Response {
    this.Route = mao.Route{"default_index","localhost","/", "GET"}
}

现在,由于我想在控制器内部定义路由,因此路由器在实例化时应读取所有控制器。 那就是问题所在。

如何将程序包名称传递给路由器,以便能够获取该程序包中的所有结构和功能? 可能吗?

您无法在Go中进行查询,因为它无法枚举包/程序中的所有类型。

一种选择是跟随database/sql程序包的database/sql ,并具有一个系统,其他程序包可以在导入时向其注册。

例如,要将PostgreSQL驱动程序与该软件包一起使用,您可以这样做:

import (
    _ "github.com/lib/pq"
    "database/sql"
)

...
db, err := sql.Open("postgres", "dbname=test")

在初始化github.com/lib/pq软件包期间注册了postgres驱动程序。 这是该软件包中的相关代码(省略了一些不相关的部分):

package pq

import (
    "database/sql"
)

type drv struct{}

func (d *drv) Open(name string) (driver.Conn, error) {
    return Open(name)
}

func init() {
    sql.Register("postgres", &drv{})
}

也许您可以创建这样的注册API来找到程序中可用的各种实现?

老实说,我认为您的做法是错误的。 “自动注册”使发生的事情难以理解,并导致难以测试和推理的代码。

我建议使控制器成为具体控制器应满足的接口,并在路由器上具有Add(c Controller)方法,以在调用主项目(导入路由器和控制器)中分配控制器。 这应该使您的代码易于理解和显式,并且更本着Go的精神。

database/sql驱动程序注册更像是黑客,不应被视为最佳实践。

我认为您应该为路由器提供一个结构(它可能是全局的,例如http.DefaultClient),然后在控制器的构造函数中,您可以将此路由器作为依赖项注入,以便为路由器。 DI +接口不仅在Go中使您的代码漂亮且可测试。

只是一个主意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM