You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go开发Twitter克隆查询关注者推文触发nil pointer dereference panic求助

问题根源

你的空指针panic由以下三个代码疏漏共同导致:

  • 调用MongoDB Aggregate 方法后没有检查返回错误,一旦聚合执行失败,返回的 cursor 就是nil,后续调用cursor.All时会直接触发空指针引用,和你给出的报错堆栈完全匹配:go.mongodb.org/mongo-driver/mongo.(*Cursor).All(0x0, ...) 中的 0x0 就代表此时cursor是空指针。
  • 聚合语句中的排序字段写错:$lookup 关联出来的推文存放在tweets字段下,$unwind后需要排序的字段是tweets.date而非根路径下的date,这个错误会直接导致Aggregate执行失败返回nil cursor。
  • 同作用域下重复声明err变量:你先通过cursor, err := col.Aggregate(...)声明了err,后续又用err := cursor.All(...)重复声明,会覆盖上层的错误信息,导致你无法捕获到Aggregate的执行错误。

修复后的db包代码

package db

import (
    "context"
    "time"
    "fmt"
    "github.com/JeffersonGarcia15/Twitter-Clone/models"
    "go.mongodb.org/mongo-driver/bson"
)

/*
ReadFollowersTweets 读取我关注的用户发布的推文
*/

func ReadFollowersTweets(ID string, page int) ([]models.ReturnFollowersTweets, bool) {
    ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
    defer cancel()

    db := MongoCN.Database("twitter")
    col := db.Collection("joins")

    skip := (page - 1) * 20

    conditions := make([]bson.M, 0)
    conditions = append(conditions, bson.M{"$match": bson.M{"userid": ID}})
    conditions = append(conditions, bson.M{
        "$lookup": bson.M{
            "from":         "tweets",
            "localField":   "userrelationid",
            "foreignField": "userid",
            "as":           "tweets",
        }})
    conditions = append(conditions, bson.M{"$unwind": "$tweets"}) // 让同一页的所有推文都采用统一结构输出
    // 修复排序字段路径,MongoDB排序用数值-1代表降序,不要用字符串desc
    conditions = append(conditions, bson.M{"$sort": bson.M{"tweets.date": -1}})
    conditions = append(conditions, bson.M{"$skip": skip})
    conditions = append(conditions, bson.M{"$limit": 20})

    cursor, err := col.Aggregate(ctx, conditions)
    // 新增Aggregate错误检查,避免拿到nil cursor
    if err != nil {
        fmt.Println("聚合查询失败:", err.Error())
        return nil, false
    }
    var result []models.ReturnFollowersTweets

    // 去掉重复的短声明,直接复用之前的err变量
    err = cursor.All(ctx, &result)
    if err != nil {
        fmt.Println("读取游标失败:", err.Error())
        return result, false
    }
    return result, true
}

额外优化建议

路由层中返回成功状态码用http.StatusCreated(201)不符合RESTful规范,读取类接口成功应该返回http.StatusOK(200)。

内容的提问来源于stack exchange,提问作者Adilson Jurado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:15:01