showliuzp 2025-10-27 16:51 采纳率: 84.3%
浏览 3
已结题

golang 强制类型转换报错


//聊天数据结构
type ChatMsg struct{
    Base        ChatMsgBase     `json:"base_info"`  //基础数据结构
    OperatorId  int64           `json:"operator_id,omitempty"`
    MsgDetail   *ChatMsgDetail   `json:"msg_detail,omitempty"`
}

type ChatMsgBase struct{
    Act     int     `json:"act"`        //动作定义,1:请求建立连接 2:连接建立 3:发送消息,4:建立连接失败 5、已建立连接,关闭当前连接 6、上报已读
    Msg     string  `json:"msg"`        //消息
}

/*kafka/转发到客户端定义的数据结构*/
type ChatMsgDetail struct {
    Type  int    `json:"type"`
    UUID  string `json:"uuid"`
    Uid   int64  `json:"uid"`
    ToUid int64  `json:"to_uid"`
    Data  any    `json:"data"`
}


//读取数据包
    for {
        loop:

        msg_type, msg, err := conn.ReadMessage()
        if err != nil{
            if !websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
                logx.Error(fmt.Sprintf("tags:%+v,连接非正常关闭,err:%+v",ws.LogTag,err))
            }

            break
        }

        unpack_data,err := unpack_msg(&msg)

        req := MessagePushReq{
            Uid:msg_detail.Uid,
            ToUid:msg_detail.ToUid,
            Flag:int32(msg_detail.Type),
            Uuid:msg_detail.UUID,
            Content:msg_detail.Data.(string),
        }
}

//拆包消息
func unpack_msg(bytes *[]byte) (msg *iapi.ChatMsg, err error){
    msg = new(iapi.ChatMsg)
    err = json.Unmarshal(*bytes,msg)

    return
}

type MessagePushReq struct {
    state         protoimpl.MessageState `protogen:"open.v1"`
    Uid           int64                  `protobuf:"varint,1,opt,name=uid,proto3" json:"uid,omitempty"`
    ToUid         int64                  `protobuf:"varint,2,opt,name=to_uid,json=toUid,proto3" json:"to_uid,omitempty"`
    Flag          int32                  `protobuf:"varint,3,opt,name=flag,proto3" json:"flag,omitempty"`
    Uuid          string                 `protobuf:"bytes,4,opt,name=uuid,proto3" json:"uuid,omitempty"`
    Content       string                 `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"`
}


我在读取websocket的数据后,Content:msg_detail.Data.(string),赋值的过程中产生了panic,报错panic: interface conversion: interface {} is map[string]interface {}, not string
  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-27 17:04
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:每天给自己一个希望,试着不为明天烦恼,不为昨天叹息。
    .

    根据你提供的代码和错误信息,问题出现在类型断言上。msg_detail.Data 的实际类型是 map[string]interface{},但你试图将其断言为 string 类型。

    问题分析

    从你的数据结构可以看出:

    type ChatMsgDetail struct {
        Type  int    `json:"type"`
        UUID  string `json:"uuid"`
        Uid   int64  `json:"uid"`
        ToUid int64  `json:"to_uid"`
        Data  any    `json:"data"`  // 这里可以是任何类型
    }
    

    当 JSON 数据中的 data 字段是对象时,解析后就会变成 map[string]interface{}

    解决方案

    方案1:安全的类型断言

    req := MessagePushReq{
        Uid:    msg_detail.Uid,
        ToUid:  msg_detail.ToUid,
        Flag:   int32(msg_detail.Type),
        Uuid:   msg_detail.UUID,
    }
    
    
    // 安全的类型断言
    if str, ok := msg_detail.Data.(string); ok {
        req.Content = str
    } else {
        // 如果不是字符串,可以根据需要处理
        // 例如转换为 JSON 字符串
        if dataMap, ok := msg_detail.Data.(map[string]interface{}); ok {
            jsonBytes, err := json.Marshal(dataMap)
            if err == nil {
                req.Content = string(jsonBytes)
            }
        }
        // 或者设置为空字符串
        // req.Content = ""
    }
    

    方案2:根据数据类型灵活处理

    func getContentString(data any) string {
        switch v := data.(type) {
        case string:
            return v
        case map[string]interface{}:
            // 将 map 转换为 JSON 字符串
            jsonBytes, err := json.Marshal(v)
            if err != nil {
                return ""
            }
            return string(jsonBytes)
        case []byte:
            return string(v)
        default:
            // 其他类型尝试转换为字符串
            return fmt.Sprintf("%v", v)
        }
    }
    
    
    // 使用方式
    req := MessagePushReq{
        Uid:     msg_detail.Uid,
        ToUid:   msg_detail.ToUid,
        Flag:    int32(msg_detail.Type),
        Uuid:    msg_detail.UUID,
        Content: getContentString(msg_detail.Data),
    }
    

    方案3:修改数据结构定义

    如果 data 字段在业务逻辑中应该是特定类型,可以考虑修改数据结构:

    type ChatMsgDetail struct {
        Type  int    `json:"type"`
        UUID  string `json:"uuid"`
        Uid   int64  `json:"uid"`
        ToUid int64  `json:"to_uid"`
        Data  string `json:"data"`  // 明确指定为字符串
    }
    

    完整修复示例

    for {
        msg_type, msg, err := conn.ReadMessage()
        if err != nil {
            if !websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
                logx.Error(fmt.Sprintf("tags:%+v,连接非正常关闭,err:%+v", ws.LogTag, err))
            }
            break
        }
    
    
        unpack_data, err := unpack_msg(&msg)
        if err != nil {
            logx.Error("解包消息失败:", err)
            continue
        }
    
    
        // 确保 msg_detail 不为 nil
        if unpack_data.MsgDetail == nil {
            logx.Error("MsgDetail 为 nil")
            continue
        }
    
    
        msg_detail := unpack_data.MsgDetail
    
    
        req := MessagePushReq{
            Uid:   msg_detail.Uid,
            ToUid: msg_detail.ToUid,
            Flag:  int32(msg_detail.Type),
            Uuid:  msg_detail.UUID,
        }
    
    
        // 安全处理 Content 字段
        switch content := msg_detail.Data.(type) {
        case string:
            req.Content = content
        case map[string]interface{}:
            // 根据业务需求决定如何处理
            jsonBytes, err := json.Marshal(content)
            if err == nil {
                req.Content = string(jsonBytes)
            } else {
                req.Content = "{}"
            }
        default:
            req.Content = fmt.Sprintf("%v", content)
        }
    
    
        // 继续处理 req...
    }
    

    建议

    1. 添加错误处理:在类型断言前总是检查 unpack_data.MsgDetail 是否为 nil
    2. 使用安全的类型断言:总是使用 value, ok := interface.(type) 的形式
    3. 日志记录:在处理不同类型时记录日志,便于调试

    这样可以避免 panic,并根据实际的数据类型进行适当的处理。

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

报告相同问题?

问题事件

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