type TokenHandler func(req interface{}, token_detail *TokenDetail) (interface{}, error)
//oken内容中间件处理
func WithTokenAccountValidation(handler TokenHandler) TokenHandler {
return func(req interface{}, token *TokenDetail) (interface{}, error) {
token_detail, err := tools.ParseToken((*token).Token)
if err != nil {
return nil, err
}
(*token).TokenDetail = token_detail
return handler(req, token)
}
}
方法一:
//用户管理-主播列表-主播退出
func UserStreamerQuit(r *http.Request) (resp interface{},err error){
authorization := (*r).Header.Get(types.HEADER_AUTH)
var req = new(iapi.UserStreamerStatusReq)
if resp,err = ParseReq(r,&req,"用户管理-列表-退出,前端参数错误",log_tag_user_streamer);err != nil{
return
}
wrapped_handler := func(req interface{}, token *services.TokenDetail) (resp interface{}, err error) {
req_params, ok := req.(*iapi.UserStreamerStatusReq)
if !ok {
return nil, fmt.Errorf("转换类型错误")
}
resp, err = user_streamer_obj.UserStreamerQuit(req_params, *token)
return
}
resp,err = services.WithTokenAccountValidation(wrapped_handler)(req,&(services.TokenDetail{Token:&authorization}))
return
}
方法二:
func UserStreamerStatus(r *http.Request) (resp interface{},err error){
authorization := (*r).Header.Get(types.HEADER_AUTH)
var req = new(iapi.UserStreamerStatusReq)
if resp,err = ParseReq(r,&req,"用户管理-主播列表-主播状态变更,前端参数错误",log_tag_user_streamer);err != nil{
return
}
if req.Status >2 || req.Status < 1{
return nil, response.NewErrCodeMsg(200, "参数不正确")
}
wrapped_handler := func(req interface{}, token *services.TokenDetail) (resp interface{}, err error) {
req_params, ok := req.(*iapi.UserStreamerStatusReq)
if !ok {
return nil, fmt.Errorf("转换类型错误")
}
resp, err = user_streamer_obj.UserStreamerStatus(req_params, *token)
return
}
resp,err = services.WithTokenAccountValidation(wrapped_handler)(req,&(services.TokenDetail{Token:&authorization}))
return
}
方法1和方法二都有重复调用中间的代码,比较臃肿,
臃肿点:
1、authorization := (*r).Header.Get(types.HEADER_AUTH)
2、wrapped_handler := func(req interface{}, token *services.TokenDetail) (resp interface{}, err error) {
req_params, ok := req.(*iapi.UserStreamerStatusReq)
if !ok {
return nil, fmt.Errorf("转换类型错误")
}
resp, err = user_streamer_obj.UserStreamerStatus(req_params, *token)
return
}
resp,err = services.WithTokenAccountValidation(wrapped_handler)(req,&(services.TokenDetail{Token:&authorization}))
我想对这部分代码进行复用,应该怎么做
golang中间件重复代码封装
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
3条回答 默认 最新
檀越@新空间 2025-09-27 14:26关注下午好🌅🌅🌅
本答案参考通义千问为了减少方法一和方法二中的重复代码,我们可以将公共逻辑提取为一个通用的封装函数,这样可以避免在每个处理函数中重复编写相同的逻辑。
目标
- 封装 获取 token 信息 的逻辑
- 封装 类型转换 和 调用业务逻辑 的逻辑
- 减少重复的
wrapped_handler定义
解决方案
1. 提取 Token 解析逻辑
我们将从请求中获取 token 的部分封装到一个独立函数中。
// GetTokenFromRequest 获取请求中的 token 字符串 func GetTokenFromRequest(r *http.Request) (string, error) { authHeader := r.Header.Get(types.HEADER_AUTH) if authHeader == "" { return "", fmt.Errorf("缺少 Authorization 头") } return authHeader, nil }
2. 封装通用的 handler 调用逻辑
创建一个通用函数来处理以下步骤:
- 解析 token
- 构建 TokenDetail 对象
- 创建 wrapped_handler
- 调用 WithTokenAccountValidation 中间件
- 返回结果
// HandleWithTokenAndParseReq 是一个通用的封装函数 func HandleWithTokenAndParseReq( r *http.Request, reqType interface{}, handlerFunc func(req *iapi.UserStreamerStatusReq, token *services.TokenDetail) (interface{}, error), errMsg string, logTag string, ) (interface{}, error) { // 1. 获取 token tokenStr, err := GetTokenFromRequest(r) if err != nil { return nil, err } // 2. 解析请求参数 var req = reqType if resp, err := ParseReq(r, req, errMsg, logTag); err != nil { return resp, err } // 3. 构建 TokenDetail tokenDetail := &services.TokenDetail{Token: &tokenStr} // 4. 创建 wrapped_handler wrappedHandler := func(req interface{}, token *services.TokenDetail) (interface{}, error) { reqParams, ok := req.(*iapi.UserStreamerStatusReq) if !ok { return nil, fmt.Errorf("类型转换失败") } return handlerFunc(reqParams, token) } // 5. 调用中间件 result, err := services.WithTokenAccountValidation(wrappedHandler)(req, tokenDetail) return result, err }
3. 修改方法一和方法二以使用通用函数
方法一(UserStreamerQuit)修改如下:
func UserStreamerQuit(r *http.Request) (resp interface{}, err error) { return HandleWithTokenAndParseReq( r, new(iapi.UserStreamerStatusReq), func(req *iapi.UserStreamerStatusReq, token *services.TokenDetail) (interface{}, error) { return user_streamer_obj.UserStreamerQuit(req, *token) }, "用户管理-列表-退出,前端参数错误", log_tag_user_streamer, ) }方法二(UserStreamerStatus)修改如下:
func UserStreamerStatus(r *http.Request) (resp interface{}, err error) { // 额外校验 status authorization, _ := GetTokenFromRequest(r) req := new(iapi.UserStreamerStatusReq) if resp, err := ParseReq(r, req, "用户管理-主播列表-主播状态变更,前端参数错误", log_tag_user_streamer); err != nil { return resp, err } if req.Status > 2 || req.Status < 1 { return nil, response.NewErrCodeMsg(200, "参数不正确") } return HandleWithTokenAndParseReq( r, req, func(req *iapi.UserStreamerStatusReq, token *services.TokenDetail) (interface{}, error) { return user_streamer_obj.UserStreamerStatus(req, *token) }, "用户管理-主播列表-主播状态变更,前端参数错误", log_tag_user_streamer, ) }
总结:优化点
-
统一 Token 解析逻辑 ✅
- 使用
GetTokenFromRequest封装 token 获取逻辑
- 使用
-
复用类型转换与 handler 构建逻辑 ✅
- 使用
HandleWithTokenAndParseReq统一处理请求解析、token 处理、handler 构建
- 使用
-
减少重复代码 ✅
- 每个接口只需定义自己的业务逻辑,无需重复写
wrapped_handler或 token 解析
- 每个接口只需定义自己的业务逻辑,无需重复写
最终效果
通过上述封装,你可以将原本分散在多个方法中的重复逻辑集中到一个通用函数中,提高代码可维护性和可读性。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报