showliuzp 2025-09-27 14:52 采纳率: 84.3%
浏览 2
已结题

golang中间件封装报错


services.go
type TokenHandler func(req interface{}, token_detail *TokenDetail) (interface{}, error)

//工会管理Token内容中间件处理
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)
    }
}

controller.go
// 业务逻辑处理器类型
type BusinessHandler func(req interface{}, token services.TokenDetail) (interface{}, error)

// 创建Token验证包装器
func WithTokenValidation(r *http.Request, reqPtr interface{}, errorMsg string, logTag string, businessHandler BusinessHandler) (interface{}, error) {
    authorization := r.Header.Get(types.HEADER_AUTH)
    // 解析请求参数
    resp, err := ParseReq(r, reqPtr, errorMsg, logTag)
    if err != nil {
        return resp, err
    }

    wrappedHandler := func(req interface{}, token *services.TokenDetail) (interface{}, error) {
        reqParams, ok := req.(interface{}) // 这里可以根据具体类型调整
        if !ok {
            return nil, fmt.Errorf("转换类型错误")
        }

        return businessHandler(reqParams, *token)
    }
    return services.WithTokenAccountValidation(wrappedHandler)(
        reqPtr,
        &services.TokenDetail{Token: &authorization},
    )
}

调用:
main func(){
    BusinessHandler := func(req *iapi.UserStreamerListReq, token services.TokenDetail) (interface{}, error) {
        return user_streamer_obj.UserStreamerList(req, token)
    }

    return WithTokenValidation(
        r,
        new(iapi.UserStreamerListReq),
        "获取用户管理的主播列表,前端参数错误",
        log_tag_user_streamer,
        BusinessHandler,
    )
}

在main.go执行中间件报错:
cannot use BusinessHandler (variable of type func(req *iapi.UserStreamerListReq, token services.TokenDetail) (interface{}, error)) as BusinessHandler value in argument to WithTokenValidation
  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-09-27 15:11
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你遇到的错误是因为函数签名不匹配,导致无法将 BusinessHandler 作为参数传入 WithTokenValidation 函数。


    问题分析

    1. 函数签名不一致

    • WithTokenValidation 的参数类型是:

      func WithTokenValidation(r *http.Request, reqPtr interface{}, errorMsg string, logTag string, businessHandler BusinessHandler) (interface{}, error)
      

      其中 businessHandler 是类型为:

      type BusinessHandler func(req interface{}, token services.TokenDetail) (interface{}, error)
      
    • 而你在 main.go 中定义的 BusinessHandler 是:

      func(req *iapi.UserStreamerListReq, token services.TokenDetail) (interface{}, error)
      

      这里的 req 类型是 *iapi.UserStreamerListReq,而不是 interface{},因此函数签名不匹配,Go 编译器报错。


    解决方案

    ✅ 解决方案一:统一函数签名(推荐)

    步骤一:修改 BusinessHandler 的函数签名

    BusinessHandlerreq 参数改为 interface{},以与 WithTokenValidation 的定义一致。

    // 修改前
    func(req *iapi.UserStreamerListReq, token services.TokenDetail) (interface{}, error)
    
    // 修改后
    func(req interface{}, token services.TokenDetail) (interface{}, error)
    

    步骤二:在调用时进行类型断言

    BusinessHandler 内部对 req 进行类型断言:

    func BusinessHandler(req interface{}, token services.TokenDetail) (interface{}, error) {
        reqParams, ok := req.(*iapi.UserStreamerListReq)
        if !ok {
            return nil, fmt.Errorf("转换类型错误")
        }
        return user_streamer_obj.UserStreamerList(reqParams, token)
    }
    

    ✅ 解决方案二:使用泛型(Go 1.18+)

    如果你使用的是 Go 1.18 或更高版本,可以使用泛型来实现更灵活的类型处理。

    步骤一:定义泛型函数

    func WithTokenValidation[T any](r *http.Request, reqPtr T, errorMsg string, logTag string, businessHandler func(T, services.TokenDetail) (interface{}, error)) (interface{}, error) {
        // 解析请求参数
        resp, err := ParseReq(r, reqPtr, errorMsg, logTag)
        if err != nil {
            return resp, err
        }
    
        wrappedHandler := func(req interface{}, token *services.TokenDetail) (interface{}, error) {
            reqParams, ok := req.(T)
            if !ok {
                return nil, fmt.Errorf("转换类型错误")
            }
    
            return businessHandler(reqParams, *token)
        }
    
        return services.WithTokenAccountValidation(wrappedHandler)(
            reqPtr,
            &services.TokenDetail{Token: &authorization},
        )
    }
    

    步骤二:调用时使用泛型

    func main() {
        BusinessHandler := func(req *iapi.UserStreamerListReq, token services.TokenDetail) (interface{}, error) {
            return user_streamer_obj.UserStreamerList(req, token)
        }
    
        return WithTokenValidation(
            r,
            new(iapi.UserStreamerListReq),
            "获取用户管理的主播列表,前端参数错误",
            log_tag_user_streamer,
            BusinessHandler,
        )
    }
    

    注意:你需要确保 ParseReqWithTokenAccountValidation 等函数也支持泛型或适配泛型逻辑。


    总结

    | 问题 | 原因 | 解决方法 | |------|------|----------| | 报错:cannot use BusinessHandler as BusinessHandler value in argument to WithTokenValidation | 函数签名不匹配 | 统一函数签名使用泛型 |


    最终修改建议(推荐)

    修改后的 controller.go 中的 WithTokenValidation

    func WithTokenValidation(r *http.Request, reqPtr interface{}, errorMsg string, logTag string, businessHandler BusinessHandler) (interface{}, error) {
        authorization := r.Header.Get(types.HEADER_AUTH)
        // 解析请求参数
        resp, err := ParseReq(r, reqPtr, errorMsg, logTag)
        if err != nil {
            return resp, err
        }
    
        wrappedHandler := func(req interface{}, token *services.TokenDetail) (interface{}, error) {
            reqParams, ok := req.(interface{})
            if !ok {
                return nil, fmt.Errorf("转换类型错误")
            }
    
            return businessHandler(reqParams, *token)
        }
    
        return services.WithTokenAccountValidation(wrappedHandler)(
            reqPtr,
            &services.TokenDetail{Token: &authorization},
        )
    }
    

    修改后的 main.go 中的 BusinessHandler

    func BusinessHandler(req interface{}, token services.TokenDetail) (interface{}, error) {
        reqParams, ok := req.(*iapi.UserStreamerListReq)
        if !ok {
            return nil, fmt.Errorf("转换类型错误")
        }
        return user_streamer_obj.UserStreamerList(reqParams, token)
    }
    

    如需进一步优化代码结构,可考虑引入中间层或使用接口抽象。欢迎继续提问!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 10月5日
  • 已采纳回答 9月27日
  • 创建了问题 9月27日