//聊天数据结构
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
golang 强制类型转换报错
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
3条回答 默认 最新
关注让【宝码香车】来帮您解答,本回答参考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... }建议
- 添加错误处理:在类型断言前总是检查
unpack_data.MsgDetail是否为 nil - 使用安全的类型断言:总是使用
value, ok := interface.(type)的形式 - 日志记录:在处理不同类型时记录日志,便于调试
这样可以避免 panic,并根据实际的数据类型进行适当的处理。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 添加错误处理:在类型断言前总是检查