Golang通用HTTP请求处理函数实现

Golang通用HTTP请求处理函数实现 以下是用于处理 HTTP 请求的通用函数

func Process[Req GoLibRequest, Resp GoLibResponse](w http.ResponseWriter, r *http.Request, processFunc func(request GoLibRequest, response *GoLibResponse) error) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {

	request := GoLibRequest{MsgId: GetMsgID()}
	response := GoLibResponse{MsgId: GetMsgID()}

	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		Logger.Errorf("Decoding body failed: %v", err)
		resErr := NewHTTPError(err, 400, "Bad request : invalid JSON.", "EGN002")
		response.Error = resErr
		json.NewEncoder(w).Encode(response)
		return
	}

	resErr := processFunc(request, &response)
	if resErr != nil {
		Logger.Errorf("Unable to process request: %v", resErr)
		response.Error = resErr
		w.WriteHeader(http.StatusInternalServerError)
	} else {
		w.WriteHeader(200)
	}

	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(response); err != nil {
		log.Printf("Encoding response failed: %v", err)
	}
}
}

如何正确地将此函数传递给 mux 路由器。

目前按以下方式传递

sm := http.NewServeMux()
sm.HandleFunc("/login", lib.Process(ProcessLogin))

	s := &http.Server{
	Addr:         ":9091",
	Handler:      sm,
	IdleTimeout:  120 * time.Second,
	ReadTimeout:  1 * time.Second,
	WriteTimeout: 1 * time.Second,
}

go func() {
	err := s.ListenAndServe()
	if err != nil {
		lib.Logger.Error(err)
	}
}()

更多关于Golang通用HTTP请求处理函数实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang通用HTTP请求处理函数实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个类型参数使用不当的问题。你的 Process 函数期望三个参数,但调用时只传递了一个 processFunc

问题在于你的 Process 函数签名定义有误。它应该返回 http.HandlerFunc,而不是接受 wr 作为参数。以下是修正后的实现:

func Process[Req GoLibRequest, Resp GoLibResponse](processFunc func(request Req, response *Resp) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        var request Req
        var response Resp
        
        // 如果请求类型有 MsgId 字段,可以这样初始化
        // 需要确保 Req 和 Resp 类型有相应的方法
        if reqWithMsgID, ok := any(&request).(interface{ SetMsgID(string) }); ok {
            reqWithMsgID.SetMsgID(GetMsgID())
        }
        
        if respWithMsgID, ok := any(&response).(interface{ SetMsgID(string) }); ok {
            respWithMsgID.SetMsgID(GetMsgID())
        }

        if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
            Logger.Errorf("Decoding body failed: %v", err)
            resErr := NewHTTPError(err, 400, "Bad request : invalid JSON.", "EGN002")
            
            // 需要确保 Resp 类型有 Error 字段
            if respWithError, ok := any(&response).(interface{ SetError(error) }); ok {
                respWithError.SetError(resErr)
            }
            
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(http.StatusBadRequest)
            json.NewEncoder(w).Encode(response)
            return
        }

        resErr := processFunc(request, &response)
        if resErr != nil {
            Logger.Errorf("Unable to process request: %v", resErr)
            if respWithError, ok := any(&response).(interface{ SetError(error) }); ok {
                respWithError.SetError(resErr)
            }
            w.WriteHeader(http.StatusInternalServerError)
        } else {
            w.WriteHeader(200)
        }

        w.Header().Set("Content-Type", "application/json")
        if err := json.NewEncoder(w).Encode(response); err != nil {
            log.Printf("Encoding response failed: %v", err)
        }
    }
}

然后定义你的请求和响应类型:

type LoginRequest struct {
    MsgId  string `json:"msg_id"`
    Username string `json:"username"`
    Password string `json:"password"`
}

func (r *LoginRequest) SetMsgID(id string) {
    r.MsgId = id
}

type LoginResponse struct {
    MsgId  string `json:"msg_id"`
    Token  string `json:"token,omitempty"`
    Error  string `json:"error,omitempty"`
}

func (r *LoginResponse) SetMsgID(id string) {
    r.MsgId = id
}

func (r *LoginResponse) SetError(err error) {
    if err != nil {
        r.Error = err.Error()
    }
}

处理函数:

func ProcessLogin(request LoginRequest, response *LoginResponse) error {
    // 验证逻辑
    if request.Username == "admin" && request.Password == "password" {
        response.Token = "generated-jwt-token"
        return nil
    }
    return errors.New("invalid credentials")
}

路由器配置:

sm := http.NewServeMux()
sm.HandleFunc("/login", lib.Process[LoginRequest, LoginResponse](ProcessLogin))

s := &http.Server{
    Addr:         ":9091",
    Handler:      sm,
    IdleTimeout:  120 * time.Second,
    ReadTimeout:  1 * time.Second,
    WriteTimeout: 1 * time.Second,
}

go func() {
    err := s.ListenAndServe()
    if err != nil {
        lib.Logger.Error(err)
    }
}()

关键修正:

  1. Process 函数现在只接受 processFunc 参数,返回 http.HandlerFunc
  2. 使用类型断言来安全地访问 MsgIdError 字段
  3. 类型参数 ReqResp 在函数签名中正确使用
  4. 处理函数现在可以正确传递给 HandleFunc
回到顶部