golang中集中处理HTTP处理器错误的简单模式

B站影视 电影资讯 2025-05-18 10:01 2

摘要:func SomeHandler(w http.ResponseWriter, r *http.Request) { data, err := fetchSomeData if err != nil { http.error(w, "Failed to fet

在这篇简短的文章中,我将与您分享一个我用来集中处理HTTP处理器错误的简单模式。

如果您已经编写过任何数量的Go HTTP 服务器,您可能已经厌倦了一次又一次地编写相同的错误处理代码:

func SomeHandler(w http.ResponseWriter, r *http.Request) { data, err := fetchSomeData if err != nil { http.error(w, "Failed to fetch data", http.StatusInternalServerError) log.Printf("Error fetching data: %v", err) return } // 更多的错误处理...}

这段代码是重复的,并且用样板代码污染了您的处理器,而不是业务逻辑。

一个更好的方法是简单地更改您的处理器以返回错误,而不是直接处理它们。

package httperrorimport ( "errors" "net/http")type HTTPError struct { error Code int}func New(code int, message string) *HTTPError { return &HTTPError{ error: errors.New(message), Code: code, }}func NotFound(message string) *HTTPError { return New(http.StatusNotFound, message)}// 根据需要添加更多辅助函数...type HTTPHandlerWithErr func(http.ResponseWriter, *http.Request) error// Handle 包装您的错误返回处理器func (r *Router) Handle(pattern string, handler HTTPHandlerWithErr) { r.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { if err := handler(w, r); err != nil { // 检查它是否为HTTPError var httpErr *httperror.HTTPError if errors.As(err, &httpErr) { http.Error(w, err.Error, httpErr.Code) slog.Debug("http error", "code", httpErr.Code, "err", err.Error) } else { // 默认为500 http.Error(w, err.Error, http.StatusInternalServerError) slog.Error("internal server error", "err", err.Error) } } })}

这个包装器处理了所有错误处理的繁重工作。它使用 errors.As 检查错误是否为 HTTPError 并提取状态码。

为GET、POST、PUT、PATCH、DELETE等方法...

func (c *containersController) Show(w http.ResponseWriter, r *http.Request) error { id := r.PathValue("id") container, err := c.service.FindContainer(id) if err != nil { if errors.Is(err, store.ErrNotFound) { return httperror.NotFound("container not found") } return err } return JSON.NewEncoder(w).Encode(container)}

看看这个处理器现在有多干净!它专注于它的工作,而不是错误处理的杂技。

我整理了很多golang的实用技巧,可以说是一本实用的golang避坑指南,快速从初级到高级的转变提效技巧都在专栏里有介绍,感兴趣的可以进一步阅读

来源:SuperOps

相关推荐