showliuzp 2025-09-23 17:46 采纳率: 84.3%
浏览 8
已结题

golang函数中间件


var operator_obj = services.NewOperator()

type OperatorHandler func(req interface{}, token *string) (interface{}, error)

// Token 验证中间件
func WithTokenValidation(handler OperatorHandler) OperatorHandler {
    return func(req interface{}, token *string) (interface{}, error) {
        token_detail, err := tools.ParseTokens(token)
        fmt.Printf("tokenDetail:%+v",token_detail)
        if err != nil {
            return nil, err
        }
        // 可以将 tokenDetail 传递给业务处理函数
        // 这里需要根据具体需求调整
        return handler(req, token)
    }
}


func OperatorList(r *http.Request)(resp interface{}, err error){
    authorization := (*r).Header.Get(types.HEADER_AUTH)
    var req = new(iapi.OperatorListReq)
    if resp,err = ParseReq(r,&req,"获取操作者列表,前端参数错误",log_tag_operator);err != nil{
                return
    }

    PageSetComm(&(req.PageReq))

    list,err := WithTokenValidation(operator_obj.List,req,authorization)

    return
}

services的定义:
func (o *Operator) List(req *iapi.OperatorListReq, token *string)(resp iapi.OperatorListResp,err error){
    list,total,err := dao.OperatorList(req,10)
}

WithTokenValidation是一个函数中间件,OperatorList调用services的方法,WithTokenValidation(operator_obj.List,req,authorization),operator_obj.List是调用的services的方法,是调用的不对么,报错:
declared and not used: list
assignment mismatch: 2 variables but WithTokenValidation returns 1 value
 too many arguments in call to WithTokenValidation
        have (func(req *iapi.OperatorListReq, token *string) (resp iapi.OperatorListResp, err error), *iapi.OperatorListReq, string)
  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-09-23 17:47
    关注

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

    你提到的错误信息非常关键,我们来逐步分析并解决这个问题。


    问题分析

    1. WithTokenValidation 的定义

    func WithTokenValidation(handler OperatorHandler) OperatorHandler {
        return func(req interface{}, token *string) (interface{}, error) {
            token_detail, err := tools.ParseTokens(token)
            fmt.Printf("tokenDetail:%+v",token_detail)
            if err != nil {
                return nil, err
            }
            // 可以将 tokenDetail 传递给业务处理函数
            // 这里需要根据具体需求调整
            return handler(req, token)
        }
    }
    

    这个中间件接收一个 OperatorHandler 类型的函数,并返回一个新的 OperatorHandler 函数。它接受两个参数:req interface{}token *string,并返回 (interface{}, error)


    2. operator_obj.List 的定义

    假设 operator_obj.List 是这样的:

    func (o *Operator) List(req *iapi.OperatorListReq, token *string) (resp iapi.OperatorListResp, err error) {
        list, total, err := dao.OperatorList(req, 10)
        return resp, err
    }
    

    这说明 operator_obj.List 是一个方法,其签名是:

    func (o *Operator) List(req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error)
    

    OperatorHandler 的定义是:

    type OperatorHandler func(req interface{}, token *string) (interface{}, error)
    

    所以,operator_obj.List 并不完全匹配 OperatorHandler 的类型,因为它的参数和返回值与 OperatorHandler 不一致。


    3. 调用 WithTokenValidation 的方式错误

    你在 OperatorList 中这样调用:

    list, err := WithTokenValidation(operator_obj.List, req, authorization)
    

    这是错误的,因为:

    • WithTokenValidation 接收的是一个 OperatorHandler(即一个函数),而不是直接调用该函数。
    • 你传入了三个参数:operator_obj.List, req, authorization,但 WithTokenValidation 只接受一个参数(即 handler)。

    解决方案

    步骤 1:适配 operator_obj.List 到 OperatorHandler

    你需要将 operator_obj.List 转换为符合 OperatorHandler 签名的函数。

    // 将 operator_obj.List 转换为 OperatorHandler
    func adaptOperatorList(req *iapi.OperatorListReq, token *string) (interface{}, error) {
        resp, err := operator_obj.List(req, token)
        return resp, err
    }
    

    步骤 2:使用 WithTokenValidation 包装适配后的函数

    // 使用 WithTokenValidation 包装适配后的函数
    wrappedHandler := WithTokenValidation(adaptOperatorList)
    

    步骤 3:调用包装后的函数

    resp, err := wrappedHandler(req, &authorization)
    

    最终修改后的代码示例

    // 修改后的 OperatorList 函数
    func OperatorList(r *http.Request) (resp interface{}, err error) {
        authorization := (*r).Header.Get(types.HEADER_AUTH)
        var req = new(iapi.OperatorListReq)
        if resp, err = ParseReq(r, &req, "获取操作者列表,前端参数错误", log_tag_operator); err != nil {
            return
        }
    
        PageSetComm(&(req.PageReq))
    
        // 适配 operator_obj.List 到 OperatorHandler
        adaptedHandler := func(req interface{}, token *string) (interface{}, error) {
            reqTyped, ok := req.(*iapi.OperatorListReq)
            if !ok {
                return nil, errors.New("invalid request type")
            }
            return operator_obj.List(reqTyped, token)
        }
    
        // 使用中间件包装
        wrappedHandler := WithTokenValidation(adaptedHandler)
    
        // 调用包装后的函数
        result, err := wrappedHandler(req, &authorization)
        return result, err
    }
    

    总结

    | 问题 | 解决方案 | |------|----------| | WithTokenValidation 被错误地调用 | 改为只传入 OperatorHandler,而不是直接调用 | | operator_obj.List 不匹配 OperatorHandler | 通过适配器函数将其转换为兼容的格式 | | 参数数量错误 | 正确理解中间件的使用方式 |


    如果你有更多关于中间件设计或 Golang 类型转换的问题,欢迎继续提问!

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

报告相同问题?

问题事件

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