package rsp import ( "github.com/labstack/echo/v4" "net/http" ) // GuardFunc 参数守卫函数前面 type GuardFunc[T any] func(c echo.Context, req *T) error // ServeFunc 参数处理函数签名 type ServeFunc[T any, R any] func(c echo.Context, req *T) (*R, error) // ServeWithDataFunc 参数处理函数签名,支持自定义数据 type ServeWithDataFunc[T any, R any, O any] func(c echo.Context, req *T, opt O) (*R, error) // RespondFunc 数据响应函数前面 type RespondFunc[R any] func(c echo.Context, res *R) error // Handle 通用 CRUD 函数构造器,具体参数与函数 HandleWithData 保持一致 func Handle[T any, R any](guard GuardFunc[T], serve ServeFunc[T, R], respond ...RespondFunc[R]) echo.HandlerFunc { return HandleWithData[T, R, any](guard, func(c echo.Context, req *T, opt any) (*R, error) { return serve(c, req) }, nil, respond...) } // HandleWithData 通用 CRUD 函数构造器,可以预置数据 // // 参数 guard 可以为空值,表示无参数守卫; // 参数 serve 必传; // 参数 data 为自定义数据,该值最好不可被修改; // 参数 respond 为自定义响应函数,若未指定,内部将使用 Ok 或 Created 来响应结果。 func HandleWithData[T any, R any, D any](guard GuardFunc[T], serve ServeWithDataFunc[T, R, D], data D, respond ...RespondFunc[R]) echo.HandlerFunc { if serve == nil { panic("miss ServeFunc") } return func(c echo.Context) error { var req T if err := c.Bind(&req); err != nil { return err } if err := c.Validate(&req); err != nil { return err } if guard != nil { err := guard(c, &req) if err != nil { return err } } res, err := serve(c, &req, data) if err != nil { return err } for _, send := range respond { if send != nil { return send(c, res) } } // 我们认为凡是 PUT 请求,都是创建数据 // 所以这里使用 Created 函数来响应数据。 if c.Request().Method == http.MethodPut { return Created(c, res) } return Ok(c, res) } } func Bind[T any](c echo.Context, guards ...GuardFunc[T]) (*T, error) { var req T if err := c.Bind(&req); err != nil { return nil, err } if err := c.Validate(&req); err != nil { return nil, err } for _, guard := range guards { if err := guard(c, &req); err != nil { return nil, err } } return &req, nil }