去程:反思catch22反映包(Go: Reflection catch22 reflect pac

2019-10-19 11:18发布

好吧..我有,或者写一个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"}
}

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

我如何通过包名到我的路由器,它能够获得该包中所有的结构和功能? 它甚至有可能?

Answer 1:

什么你问的是不可能去,因为它没有办法枚举所有类型的包/程序。

一个替代办法是遵循的领先database/sql包,并有一个系统,其它软件包可以在导入时用它注册。

例如,采用与包PostgreSQL驱动,你可以做:

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

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

Postgres的驱动程序在初始化的过程中注册github.com/lib/pq包。 下面是从包(eliding不相关的一些部件)相关的代码:

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像这样查找程序中提供的各种实现方式?



Answer 2:

老实说,我认为你这样做了错误的方式。 “自动登记”被混淆发生了什么,并会导致代码难以测试和推理。

我建议做控制器,应该由具体的控制器应满足的接口,并有一个方法Add(c Controller)在路由器上的调用主项目控制器(即进口路由器和控制器)分配。 这应该使你的代码可以理解的,明确的,更多的是去的精神。

database/sql驱动的注册更是一个黑客,不应该被认为是最佳做法。



Answer 3:

我想你应该有一个路由器的结构(这很可能是全球性的,像http.DefaultClient),然后在你的控制器构造函数你能够注入该路由器作为依赖,使相关的路线注入了路由器。 DI +接口,使你的代码不错,可测试,不仅在围棋。

只是一个想法。



文章来源: Go: Reflection catch22 reflect package
标签: reflection go