检索模型(结构)列表的通用方法

Generic method for retrieving list of models (structs)

我正在尝试为我的服务创建基本的 CRUD。它基于在结构中创建的数据模型。问题是我真的不想重复 CRUD 方法的代码。例如,我将 ModelA 和 ModelB 定义为结构:

type ModelA struct {
    ID              bson.ObjectId     `json:"ID,omitempty" bson:"_id,omitempty"`
    Slug            string            `json:"slug" bson:"slug,omitempty"`
    Creator         string            `json:"-" bson:"creator,omitempty"`
    DefaultLanguage string            `json:"defaultLanguage" bson:"defaultLanguage,omitempty"`
}

type ModelB struct {
    ID              bson.ObjectId     `json:"ID,omitempty" bson:"_id,omitempty"`
    Type            string            `json:"type" bson:"type,omitempty"`
}

我想要的是制作通用方法来检索给定模型的数组。使用模型对我来说很重要。我可以使用纯 interface{} 类型快速完成,但会丢失模型功能,例如在 JSON 输出中隐藏某些属性(例如 ModelA.Creator)。

到目前为止,我已经创建了用于创建新数据和检索单个模型的通用方法。这是示例代码:

// GET: /modelsa/{:slug}
func (r *Routes) GetModelA(w rest.ResponseWriter, req *rest.Request) {
    // set model as ModelA
    var model models.ModelA
    r.GetBySlug(w, req, &model, "models")
}

// GET: /modelsb/{:slug}
func (r *Routes) GetModelB(w rest.ResponseWriter, req *rest.Request) {
    // set model as ModelB
    var model models.ModelB
    r.GetBySlug(w, req, &model, "models")
}

func (r *Routes) GetBySlug(w rest.ResponseWriter, req *rest.Request, m interface{}, collection string) {
    slug := req.PathParam("slug")

    if err := r.GetDocumentBySlug(slug, collection, m, w, req); err != nil {
        rest.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.WriteJson(m)
}

GetModelAGetModelB 是使用通用方法 GetBySlug 的路由处理程序,即 returns 由给定模型格式化的 JSON。

我想做同样的事情,但使用给定模型的数组。到目前为止,我在将结果转换为结构时遇到了问题:

// GET /modelsa/
func (r *Routes) GetModels(w rest.ResponseWriter, req *rest.Request) {
    // I think in this case I don't have to pass an array of struct
    // because the given struct is only reference. It could be:
    // var result models.ModelA as well. Converting it into array could 
    // be done in GetList() method
    var result []models.ModelA
    r.GetList(w, req, &result, "models")
}

func (r *Routes) GetList(w rest.ResponseWriter, req *rest.Request, res interface{}, col string) {

}

我无法将 res 参数设置为 interface{} 数组。另外,如果我尝试在 GetList() 方法中将结果转换为 []interface{},我不能将其转换为 res 参数,因为它不是数组。

有什么好的方法吗?也许我想错了,应该重新设计方法?任何建议将不胜感激。

您可以声明表示模型切片的新类型。例如,

type ModelAList []ModelA
type ModelBList []ModelB

然后当您将这些新类型的变量传递给您的 r.GetDocumentBySlug() 时,encoding/json 包中的函数将相应地解组切片。

您可以找到工作示例 here (marshaling) and here (unmarshaling)