showliuzp 2025-09-18 10:54 采纳率: 84.3%
浏览 3
已结题

golang es解析错误


    //聊天记录结构
    type chat_list struct {
        Createat    int    `json:"create_at"`
        ToUid       int64    `json:"to_uid"`
        Uid         int    `json:"uid"`
        Content     string `json:"content"`
    }

    skip := (req.Page - 1) * req.PageSize

    boolQuery := elastic.NewBoolQuery()

    subQuery1 := elastic.NewBoolQuery().
    Must(elastic.NewTermQuery("to_uid", req.StreamerId)).
    Must(elastic.NewTermQuery("uid", req.MemberId))

    subQuery2 := elastic.NewBoolQuery().
    Must(elastic.NewTermQuery("to_uid", req.MemberId)).
    Must(elastic.NewTermQuery("uid", req.StreamerId))
    boolQuery = boolQuery.Should(subQuery1, subQuery2).MinimumShouldMatch("1")

    searchResult, err := types.EsClient.Search().
        Index(types.LU_CHANT_INDEX).
        Query(boolQuery).
        Sort("create_at", true).
        From(skip). //第几页
        Size((*req).PageSize).   //每页多少条
        Pretty(true).//返回json
        Do(ctx)


    //fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

    if searchResult.TotalHits() < 1{
        resp.List = make([]iapi.GuildStreamerChatList,0)
        return
    }

    var chat_detail chat_list
    //var member_id int64
    for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) {
                //主播为接收者,uid一定为会员
                if (*req).StreamerId == item.ToUid{
                    member_id = item.Uid()
                }

                if (*req).StreamerId == item.Uid{
                    member_id = item.ToUid
                }
        break
    }

通过for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) 解析数据到chat_detail里,报错:item.ToUid undefined (type interface{} has no field or method ToUid)

  • 写回答

5条回答 默认 最新

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

    上午好☀️☀️☀️️
    本答案参考通义千问

    你遇到的错误是:

    item.ToUid undefined (type interface{} has no field or method ToUid)
    

    这表明 item 是一个 interface{} 类型,而你试图访问它的字段 ToUidUid 等,但这些字段在 interface 中并不存在。


    ✅ 问题原因分析

    在使用 searchResult.Each(reflect.TypeOf(chat_detail)) 时,Elasticsearch 的 Go 客户端会返回一个 interface{} 类型的值。你需要将这个 interface{} 转换为你的结构体类型(即 chat_list),才能访问其字段。


    ✅ 解决方案

    1. item 强制转换为 chat_list 类型

    在遍历 searchResult.Each(...) 时,每个 item 是一个 interface{},你需要将其转换为你的结构体类型。

    2. 修改代码如下:

    for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) {
        // 将 item 转换为 chat_list 类型
        chatItem, ok := item.(chat_list)
        if !ok {
            continue // 如果类型转换失败,跳过
        }
    
        // 现在可以安全地访问 chatItem 的字段
        if (*req).StreamerId == chatItem.ToUid {
            member_id = chatItem.Uid
        }
    
        if (*req).StreamerId == chatItem.Uid {
            member_id = chatItem.ToUid
        }
    
        break
    }
    

    ✅ 详细说明

    • searchResult.Each(reflect.TypeOf(chat_detail)) 返回的是一个 []interface{}
    • 每个 item 是一个 interface{},需要通过类型断言转换为 chat_list
    • 使用 item.(chat_list) 进行类型断言,如果成功则可以访问其字段。
    • 如果类型不匹配,可以通过 if !ok 来处理异常情况。

    ✅ 推荐优化建议

    为了更安全和清晰地解析 Elasticsearch 查询结果,建议使用 SearchResult.Hits() 方法,然后遍历 Hit 对象,并使用 Unmarshal 来反序列化到结构体中。

    ✅ 优化后的完整代码示例:

    // 执行搜索
    searchResult, err := types.EsClient.Search().
        Index(types.LU_CHANT_INDEX).
        Query(boolQuery).
        Sort("create_at", true).
        From(skip).
        Size(req.PageSize).
        Pretty(true).
        Do(ctx)
    
    if err != nil {
        // 处理错误
    }
    
    // 遍历查询结果
    var chat_detail chat_list
    for _, hit := range searchResult.Hits.Hits {
        // 反序列化到 chat_detail
        if err := hit.Source.Unmarshal(&chat_detail); err != nil {
            continue
        }
    
        // 访问字段
        if req.StreamerId == chat_detail.ToUid {
            member_id = chat_detail.Uid
        } else if req.StreamerId == chat_detail.Uid {
            member_id = chat_detail.ToUid
        }
    
        break
    }
    

    📌 总结

    | 步骤 | 说明 | |------|------| | 1 | searchResult.Each(...) 返回的是 interface{},不能直接访问结构体字段 | | 2 | 使用 item.(chat_list) 进行类型断言,确保能访问结构体字段 | | 3 | 更推荐使用 searchResult.Hits.Hitshit.Source.Unmarshal(...) 来解析数据 |


    如果你还有其他关于 Elasticsearch 或 Golang 的问题,欢迎继续提问!

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

报告相同问题?

问题事件

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