2 回答
TA贡献1880条经验 获得超4个赞
通过将解码调用和错误处理移至可重用函数来最大程度地减少代码重复:
// 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
}
}
TA贡献1842条经验 获得超12个赞
最好抽象细节以提供有关您的处理程序所做工作的高级图片。
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)
}
可能您应该编写自己的响应包或检查开源中的可用内容。然后你就可以在任何地方使用这个具有相同响应结构的响应包。
- 2 回答
- 0 关注
- 62 浏览
添加回答
举报