2016-12-16 152 views
1

我需要创建一个REST API一个HTTP处理程序。如何在Go中编写通用处理程序?

这REST API都存储在一个数据库(MongoDB的在我的情况)许多不同的对象。

目前,我需要写每对象操作一个处理程序。

我想找到一种方法,就像它可能与泛型编写一个通用的处理程序可以处理一个特定的动作,但对于任何类型的对象(如基本上它只是CRUD在大多数的情况下)

如何我可以这样做吗?

这里是我想处理程序的例子转变为一个通用的一个:

func IngredientIndex(w http.ResponseWriter, r *http.Request) { 
    w.Header().Set("Content-Type", "application/json; charset=UTF-8") 
    db := r.Context().Value("Database").(*mgo.Database) 
    ingredients := []data.Ingredient{} 
    err := db.C("ingredients").Find(bson.M{}).All(&ingredients) 
    if err != nil { 
     panic(err) 
    } 
    json.NewEncoder(w).Encode(ingredients) 
} 

func IngredientGet(w http.ResponseWriter, r *http.Request) { 
    w.Header().Set("Content-Type", "application/json; charset=UTF-8") 
    vars := mux.Vars(r) 
    logger := r.Context().Value("Logger").(zap.Logger) 
    db := r.Context().Value("Database").(*mgo.Database) 
    ingredient := data.Ingredient{} 
    err := db.C("ingredients").Find(bson.M{"_id": bson.ObjectIdHex(vars["id"])}).One(&ingredient) 
    if err != nil { 
     w.WriteHeader(404) 
     logger.Info("Fail to find entity", zap.Error(err)) 
    } else { 
     json.NewEncoder(w).Encode(ingredient) 
    } 
} 

基本上,我需要这样的处理程序(这是我的暂定不工作):

func ObjectIndex(collection string, container interface{}) func(http.ResponseWriter, *http.Request) { 
    return func(w http.ResponseWriter, r *http.Request) { 
     w.Header().Set("Content-Type", "application/json; charset=UTF-8") 
     db := r.Context().Value("Database").(*mgo.Database) 
     objects := container 
     err := db.C(collection).Find(bson.M{}).All(&objects) 
     if err != nil { 
      panic(err) 
     } 
     json.NewEncoder(w).Encode(objects) 
    } 

我怎么能这样做?

+0

你说,“目前,我需要在每对象动作处理器写。”这就是我使用'go generate'的原因。你不需要仿制药! – eduncan911

+1

这是一个很好的做法吗?因为基本上,这样做我依然会到处都重复的代码,这将是难以维持比拥有一个通用的代码处理大部分的情况。 – Kedare

回答

3

使用reflect包在每次调用创建一个新的容器:

​​

这样称呼它:

h := ObjectIndex("ingredients", data.Ingredient{}) 

假设data.Indgredient是片类型。

+0

真棒,这就是我一直在寻找的,谢谢! :) – Kedare

相关问题