0

我正在创建一个基本的 REST 服务。我的意图是尽可能抽象地为资源编写逻辑。我的意思是,如果我已经为端点创建了一个 CRUD 逻辑/devices,那么当我需要一个新的资源端点时/cars,我不应该在 CRUD 过程中重复自己。

在 Python 等另一种语言中,类和方法是第一类对象,可以存储在列表或字典(映射)中,然后根据需要进行实例化。在 Go 中,这似乎并不容易。我尝试使用反射包。

首先我根据这个创建一个TypeRegistry 。

var TypeRegistry = make(map[string]reflect.Type)
TypeRegistry["devices"] = reflect.TypeOf(models.Device{}) // models.Device{} is the Gorm SQL table model

然后我有处理程序创建者,它旨在处理像这样的所有类型的资源的创建(错误处理已编辑):

func CreateOneHandler(typeString string) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        defer r.Body.Close()

        jsn, _ = ioutil.ReadAll(r.Body)
        jsonBytes, _ := datamapper.CreateOne(typeString, jsn)

        w.Write(jsonBytes)
    }
}

我正在使用 Chi,所以我像这样绑定处理程序:

func addRoute(r chi.Router, endpoint string, typeString string) {
    r.Route("/"+endpoint, func(r chi.Router) {
        typeString := endpoint
        r.Post("/", CreateOneHandler(typeString))
    })
}

这个想法是,在定义 Gorm 模型之后,通过重复调用它来简单地添加路由,addRoute(r, "devices"); addRoute(r, "cars")以获得跨多个模型的一致 REST 接口。

现在CreateOne()我想在表格中插入一些东西:

func CreateOne(typeString string, json []byte) ([]byte, error) {
    modelType := typeregistry.TypeRegistry[typeString]
    value := reflect.New(modelType)
    db.Create(modelPtr.Elem()) // ==> Now this doesn't work 
}

我如何使它工作?Gorm 说“创建失败没有这样的表:值”。因为反射值或反射类型与我只是以常规方式实例化对象不同。我如何使它工作?

(附注:考虑到类型开关和类型断言的静态性质,我已经损害了我的一些设计,这可能在像 Python 这样的语言中是可能的。在我看来,使用类型开关乱扔代码是不可避免的试图明确地检查它是否是一个devicecar任何数量的新模型。在常规的面向对象语言中,这可能是简单的多态方法调用。任何指向更好设计的指针也将不胜感激。)

4

0 回答 0