英文:
How to avoid code duplication in router handling code
问题
我有一个大型路由器:
router.HandleFunc("/tags", controllers.GetTags)
router.HandleFunc("/tags/items/{tagId}", controllers.GetTaggedItemsByTagId).Methods("GET")
// ...
每个函数的结构如下:
func GetTags(w http.ResponseWriter, r *http.Request) {
tags, err := (&postgres.TagsService{}).GetTags()
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(tags)
w.Write(resp)
}
}
func GetTaggedItemsByTagId(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
tagId, err := strconv.Atoi(vars["tagId"])
items, err := (&postgres.TagsService{}).GetTaggedItemsByTagId(tagId)
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(items)
w.Write(resp)
}
}
在每个函数中,我从数据库获取数据,将结果序列化为 json
,然后返回给客户端。
我需要一些方法来避免代码重复。类似于:
func Handler(err error, data object) {
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(object)
w.Write(resp)
}
}
由于Go是一种强类型语言,我不能这样做。在这种情况下,Go中有什么最好的方法来避免代码重复?
英文:
I have a big router:
router.HandleFunc("/tags", controllers.GetTags)
router.HandleFunc("/tags/items/{tagId}", controllers.GetTaggedItemsByTagId).Methods("GET")
// ...
Each of such functions looks like:
func GetTags(w http.ResponseWriter, r *http.Request) {
tags, err := (&postgres.TagsService{}).GetTags()
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(tags)
w.Write(resp)
}
}
func GetTaggedItemsByTagId(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
tagId, err := strconv.Atoi(vars["tagId"])
items, err := (&postgres.TagsService{}).GetTaggedItemsByTagId(tagId)
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(items)
w.Write(resp)
}
}
In each of these functions I get the data from the database, serialize result to json
and return it to client.
I need something to avoid code duplication. Something like:
func Handler(err error, data object) {
if err != nil {
log.Println(err)
w.WriteHeader(500)
} else {
w.Header().Add("Content-Type", "application/json")
resp, _ := json.Marshal(object)
w.Write(resp)
}
}
I can not do this way as Go is typed language. What is the best way in Go to avoid code duplication in this case ?
答案1
得分: 3
为每个HTTP处理程序的函数签名使用一个类型:
type HandlerFunc func(w http.ResponseWriter, req *http.Request) (interface{}, error)
然后像这样包装函数:
func WrapHandler(h HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
d, err := h(w, req)
// 处理错误并发送数据
}
}
然后使用以下方式设置处理程序:
router.Get('/myroute', WrapHandler(GetTaggedItemsByTagId))
英文:
Use a type for the function signature for each of the http handlers
type HandlerFunc func(w http.ResponseWriter, req *http.Request) (interface{}, error)
Then wrap the functions like this
func WrapHandler(h HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
d, err := h(w, req)
// handle errors and sending out the data
}
Then set the handlers using
router.Get('/myroute', WrapHandler(GetTaggedItemsByTagId))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论