2

为了确保在所有请求中正确处理错误结果,我正在实现一个自定义处理程序,如http://blog.golang.org/error-handling-and-go中所述。因此,处理程序不仅可以接受w http.ResponseWriter, r *http.Request参数,还可以选择返回一个error.

我正在使用 Negroni,想知道是否可以设置一次以将所有请求包装到其中,或者是否始终必须按照以下示例中的handler每个请求进行设置?//foo

type handler func(w http.ResponseWriter, r *http.Request) error

// ServeHTTP checks for error results and handles them globally
func (fn handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if err := fn(w, r); err != nil {
        http.Error(w, err, http.StatusInternalServerError)
    }
}

// Index matches the `handler` type and returns an error
func Index(w http.ResponseWriter, r *http.Request) error {
    return errors.New("something went wrong")
}

func main() {
    router := mux.NewRouter()
    // note how `Index` is wrapped into `handler`. Is there a way to 
    // make this global? Or will the handler(fn) pattern be required 
    // for every request?
    router.Handle("/", handler(Index)).Methods("GET")
    router.Handle("/foo", handler(Index)).Methods("GET")

    n := negroni.New(
        negroni.NewRecovery(),
        negroni.NewLogger(),
        negroni.Wrap(router),
    )

    port := os.Getenv("PORT")
    n.Run(":" + port)
}
4

1 回答 1

0

r.Handle如果你愿意,你可以写一个包装器。您不能使用 Negroni 全局执行此操作,因为并非您使用的所有中间件都假定您的handler类型。

例如

// Named to make the example clear.
func wrap(r *mux.Router, pattern string, h handler) *mux.Route {
    return r.Handle(pattern, h)
}

func index(w http.ResponseWriter, r *http.Request) error {
    io.WriteString(w, "Hello")
    return nil
}

func main() {
    r := mux.NewRouter()
    wrap(r, "/", index)

    http.ListenAndServe(":8000", r)
}

我认为这并不比仅仅显式地类型转换你的处理程序(这很清楚,如果有点重复的话)或者将你的处理程序类型转换为一个结构好多少。后者您可以稍后扩展以包含线程安全字段(您的数据库池、应用程序配置等),然后您可以在每个处理程序旁边显式传递这些字段)。

实际上,您当前的路由器代码仍然清晰易读,并且(对其他人)很明显支持您的处理程序的类型。

于 2015-08-30T01:27:43.477 回答