总是尝试返回相同的响应结构时,如何最小化 Go Mux 中的重复代码?

我有大量类似于以下代码片段的代码,我只是尝试填充我的响应结构、json 编组输出、设置状态代码并返回结果:


if err := json.NewDecoder(r.Body).Decode(&user); err != nil {

            response := responses.UserResponse{

                Status:  http.StatusBadRequest,

                Message: "error",

                Data:    map[string]interface{}{"error": err.Error()},

            }

            rw.WriteHeader(http.StatusBadRequest)

            errRes, _ := json.Marshal(response)

            rw.Write(errRes)

            return

        }

我试图创建一个接收r变量(request.http)的函数来接收正文以及响应的状态代码。但注意到我必须再次检查函数外部的错误代码,然后再次执行相同的响应创建流程。


Go 专家如何尽量减少像这样的代码重复?首先有这样的代码重复可以吗?


万千封印
浏览 147回答 2
2回答

慕村225694

通过将解码调用和错误处理移至可重用函数来最大程度地减少代码重复:// Decode returns true if the request body is successfully decoded// to the value pointed to by pv. Otherwise, decode writes an error// response and returns false.func decode(rw http.ResponseWriter, r *http.Request, pv interface{}) bool {    err := json.NewDecoder(r.Body).Decode(pv)    if err == nil {        return true    }    rw.WriteHeader(http.StatusBadRequest)    json.NewEncoder(rw).Encode(map[string]any{        "status":  http.StatusBadRequest,        "message": "error",        "data":    map[string]any{"error": err.Error()},    })    return false}使用这样的功能:func userHandler(rw http.ResponseWriter, r *http.Request) {    var u UserRequest    if !decode(rw, r, &u) {        return    }}

红颜莎娜

最好抽象细节以提供有关您的处理程序所做工作的高级图片。func (h *rideHandler) handleCancelRideByPassenger(w http.ResponseWriter, r *http.Request) {    ctx := r.Context()    user := getUser(ctx)    req := &cancelRequest{}    if err := decode(r, req); err != nil {        h.logger.Error("cancel ride: problem while decoding body request", zap.String("ip", r.RemoteAddr), zap.Error(err))        h.respond.BadRequest(w, NewRESTError(reasonDecoding, "problem while decoding input parameters"))        return    }    req.PublicID = chi.URLParam(r, "id")    err := h.rideService.CancelRide(ctx, req, user)    if err != nil {        var validationErr *ValidationError        switch {        case errors.As(err, &validationErr):            h.respond.BadRequest(w, NewRESTValidationError(reasonValidation, "problem while validating request", validationErr))            return        default:            h.respond.InternalServerError(w, NewRESTError(reasonInternalError, "unknown problem occurred"))            return        }    }    h.respond.Ok(w, NewRESTResponse(&cancelRideResponse{Success: true}))}处理程序利用一些方便的糖函数来删除重复,并提供处理程序的高级概述而不是底层细节。func decode(request *http.Request, val interface{}) error {    dec := json.NewDecoder(request.Body)    dec.DisallowUnknownFields()    return dec.Decode(val)}type Responder struct {    Encoder Encoder    Before BeforeFunc    After AfterFunc    OnError OnErrorFunc}func (r *Responder) writeResponse(w http.ResponseWriter, v interface{}, status int) {    if r.Before != nil {        status, v = r.Before(w, v, status)    }    encoder := JSON    if r.Encoder != nil {        encoder = r.Encoder    }    w.Header().Set("Content-Type", encoder.ContentType())    w.WriteHeader(status)    if err := encoder.Encode(w, v); err != nil {        if r.OnError != nil {            r.OnError(err)        }    }    if r.After != nil {        r.After(v, status)    }}func (r *Responder) Ok(w http.ResponseWriter, v interface{}) {    r.writeResponse(w, v, http.StatusOK)}可能您应该编写自己的响应包或检查开源中的可用内容。然后你就可以在任何地方使用这个具有相同响应结构的响应包。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go