猿问

Golang http 服务器根据内容类型返回 html 或 json

我正在尝试使用 gorilla mux 在 Golang 中编写简单的 RESTful 应用程序。我编写了一些处理程序,如下所示:


func getUser(w http.ResponseWriter, r *http.Request) {

    if r.Header.Get("Content-type") == "application/json" {

        w.Header().Set("Content-Type", "application/json")

        u, err := _getUser(r)

        if err != nil {

            http.NotFound(w, r)

            return

        }

        json.NewEncoder(w).Encode(u) //asked for json, return json

    } else {

        w.Header().Set("Content-Type", "text/html")

        u, err := _getUser(r)

        if err != nil {

            http.NotFound(w, r)

            return

        }

        renderTemplate(w, "view", u) // asked for html, return html

    }

}

func _getUser(r *http.Request) (*User, error) {

    params := mux.Vars(r)

    for _, u := range users {

        if u.ID == params["id"] {

            return &u, nil

        }

    }

    return nil, errors.New("")

}


func main() {

    router := mux.NewRouter()

    router.HandleFunc("/v1/users/{id}", getUser).Methods("GET")

}

我在这里遇到的问题是我有很多重复。每个 CRUD 方法都必须检查内容类型并返回 json 或 html。


我想过写一个闭包


func htmlOrJSON(fn func(http.ResponseWriter, *http.Request) (interface {}, error), templateName string) http.HandlerFunc {

    return func(w http.ResponseWriter, r *http.Request) {

        if r.Header.Get("Content-type") == "application/json" {

            w.Header().Set("Content-Type", "application/json")

            result, err := fn(w, r)

            if err != nil {

                http.NotFound(w, r)

                return

            }

            json.NewEncoder(w).Encode(result)

        } else {

            w.Header().Set("Content-Type", "text/html")

            result, err := fn(w, r)

            if err != nil {

                http.NotFound(w, r)

                return

            }

            renderTemplate(w, templateName, result)

        }

    }

}


// and use as:

router.HandleFunc("/v1/users/{id}", htmlOrJSON(getUser, "view")).Methods("GET")

删除重复但看起来也不太好。谁能帮我使这段代码更清晰吗?


智慧大石
浏览 130回答 1
1回答

慕容3067478

虽然这是一个代码审查问题并且应该在 CodeReview 社区中,但我会尝试回答它。编写一个处理 HTML 和 JSON 渲染的通用函数。即使您重复某些代码,错误处理 IMO 也应该在每个处理程序上发生。它在那里更有意义,并使代码更具可读性和明确性。您很快就会发现还有其他错误需要特殊处理。从逻辑上来说,大多数API都接受查询参数http://api.com/user/1?fomtat=json。这更有意义,因为当客户端接受多种内容类型时,您就会陷入困境。const JSON = "application/json"func getUser(w http.ResponseWriter, r *http.Request) {    u, err := _getUser(r)    if err != nil {        http.NotFound(w, r)        return    }    responseBody(u, r.Header.Get("Content-type"), &w)}func responseBody(u User, contentType string, w io.writer) {    switch contentType {    case JSON:        w.Header().Set("Content-Type", JSON)        json.NewEncoder(w).Encode(u) //asked for json, return json    default:        w.Header().Set("Content-Type", "text/html")        renderTemplate(w, "view", u) // asked for html, return html    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答