如何避免路由处理代码中的代码重复问题

huangapple go评论76阅读模式
英文:

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))

huangapple
  • 本文由 发表于 2017年3月23日 21:26:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/42977404.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定