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

golang中间件函数报错

service.go
func (o *Operator) List(req *iapi.OperatorListReq, token *string)(resp *iapi.OperatorListResp,err error){
    list,total,err := dao.OperatorList(req,10)
    //list,total,err := dao.OperatorList(req,token_detail.GuildId)
    if err != nil{
        logx.Error(fmt.Sprintf("tags:%+v,获取操作员列表,mongo数据库异常,req:%+v,err:%+v", o.LogTag,req,err))

        return
    }

    seq := int64((req.Page -1) *req.PageSize)

    count := len(list)
    data := make([]iapi.OperatorList,count)
    for i:=0;i < count;i++{
        detail := list[i]

        data[i] = iapi.OperatorList{
            SeqId:seq+1,
            OperatorId:detail.Id,
            Status:detail.Status,
            CreateAt:tools.FormatDates(detail.Createat),
            OperatorComm:iapi.OperatorComm{
                Account: detail.GuildAccount,
                UserName: detail.GuildAccountName,
                Contact:detail.GuildAccountContact,
                Ratio:fmt.Sprintf("%.2f",detail.Ratio),
                Role:detail.GuildAccountRole,
            },
        }

        seq++
    }

    resp = &iapi.OperatorListResp{
        List: data,
        Page: *RespPage(total,(*req).PageSize,(*req).Page),
    }

    return
}


controller.go
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)
    wrappedHandler := WithTokenValidation(operator_obj.List)
    resp, err = wrappedHandler(req, &authorization)

    return
}

iapi.go
type OperatorListReq struct {
    StartDate   int     `json:"start_date,optional"`
    EndDate     int     `json:"end_date,optional"`
    PageReq
}

type OperatorListResp struct {
    List    []OperatorList `json:"list"`
    Page    Page            `json:"page"`
}

type OperatorList struct{
    SeqId               int64       `json:"seq_id"`
    OperatorId          int64       `json:"operator_id"`
    CreateAt            string      `json:"create_at"`
    Status              int         `json:"status"`
    OperatorComm
}

我通过中间件函数调用service里的List方法,报如下错:
 cannot use operator_obj.List (value of type func(req *iapi.OperatorListReq, token *string) (resp *iapi.OperatorListResp, err error)) as OperatorHandler value in argument to WithTokenValidation
  • 写回答

4条回答 默认 最新

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

    晚上好🌙🌙🌙
    本答案参考通义千问

    你遇到的错误是:

    cannot use operator_obj.List (value of type func(req *iapi.OperatorListReq, token *string) (resp *iapi.OperatorListResp, err error)) as OperatorHandler value in argument to WithTokenValidation
    

    这个错误的原因是类型不匹配WithTokenValidation 函数期望一个 OperatorHandler 类型的函数,但你提供的 operator_obj.List 的签名与 OperatorHandler 不一致。


    问题分析

    1. OperatorHandler 的定义

    type OperatorHandler func(req interface{}, token *string) (interface{}, error)
    
    • 接收两个参数:req interface{}token *string
    • 返回两个值:interface{}error

    2. 你的 List 方法签名

    func (o *Operator) List(req *iapi.OperatorListReq, token *string)(resp *iapi.OperatorListResp,err error)
    
    • 接收两个参数:*iapi.OperatorListReq*string
    • 返回两个值:*iapi.OperatorListResperror

    解决方案

    你需要将 List 方法适配为符合 OperatorHandler 的类型。可以通过包装函数来实现。

    步骤一:修改 List 方法的调用方式

    修改 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 的格式
        wrappedHandler := func(req interface{}, token *string) (interface{}, error) {
            // 将 req 转换为 *iapi.OperatorListReq
            reqTyped, ok := req.(*iapi.OperatorListReq)
            if !ok {
                return nil, fmt.Errorf("invalid request type")
            }
            // 调用 service 方法
            result, err := operator_obj.List(reqTyped, token)
            return result, err
        }
    
        // 使用中间件处理
        handler := WithTokenValidation(wrappedHandler)
        resp, err = handler(req, &authorization)
    
        return
    }
    

    步骤二:确保 ParseReq 正确解析请求

    你使用了 ParseReq 来解析请求体,确保它返回的是 *iapi.OperatorListReq 类型。例如:

    func ParseReq(r *http.Request, req interface{}, msg string, tag string) (interface{}, error) {
        // 解析 JSON 请求体
        decoder := json.NewDecoder(r.Body)
        if err := decoder.Decode(req); err != nil {
            logx.Error(msg, "err:", err)
            return nil, err
        }
        return req, nil
    }
    

    最终结论

    重点:

    • operator_obj.List 的签名与 OperatorHandler 不匹配,需要通过包装函数进行适配。
    • 中间件函数 WithTokenValidation 需要一个 func(req interface{}, token *string) (interface{}, error) 类型的函数,而你的 Listfunc(*iapi.OperatorListReq, *string) (*iapi.OperatorListResp, error) 类型。

    修改后的完整代码(关键部分)

    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))
    
        wrappedHandler := func(req interface{}, token *string) (interface{}, error) {
            reqTyped, ok := req.(*iapi.OperatorListReq)
            if !ok {
                return nil, fmt.Errorf("invalid request type")
            }
            result, err := operator_obj.List(reqTyped, token)
            return result, err
        }
    
        handler := WithTokenValidation(wrappedHandler)
        resp, err = handler(req, &authorization)
    
        return
    }
    

    总结

    | 问题 | 原因 | 解决方案 | |------|------|-----------| | 报错 | operator_obj.List 的签名与 OperatorHandler 不匹配 | 通过包装函数将其转换为符合 OperatorHandler 的类型 | | 类型不一致 | List 接收 *iapi.OperatorListReq,而 OperatorHandler 接收 interface{} | 使用类型断言和封装函数解决 |

    如需进一步优化或调试,请提供 ParseReqtools.ParseTokens 的实现。

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

报告相同问题?

问题事件

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