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

使用Go连接MongoDB时遇客户端断开错误及空指针Panic

问题分析与修复

核心问题

你的dbConnection函数里使用了defer client.Disconnect(...),这会导致函数返回*mongo.Collection时,MongoDB客户端已经被断开。因为defer语句会在函数执行完毕退出时立刻执行,而你返回的集合对象依赖于这个已断开的客户端,后续调用coll.Find()自然会报错client is disconnected;同时因为cursor为nil,调用cursor.All()会触发空指针panic。

修复方案

正确的做法是让MongoDB客户端的生命周期与应用程序生命周期保持一致,不要在获取集合的函数里立即断开客户端。可以将客户端初始化放在全局作用域,或者由上层调用方统一管理连接和断开逻辑。

修正后的代码示例

  1. 全局初始化客户端:
import (
    "context"
    "fmt"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

// 全局客户端变量,复用单个实例
var client *mongo.Client

func init() {
    serverAPI := options.ServerAPI(options.ServerAPIVersion1)
    opts := options.Client().ApplyURI("mongodb+srv://username:pwd@domain").SetServerAPIOptions(serverAPI)
    var err error
    client, err = mongo.Connect(context.TODO(), opts)
    if err != nil {
        panic(err)
    }
    // 可选:验证连接是否正常
    if err := client.Ping(context.TODO(), nil); err != nil {
        panic(err)
    }
}

// 单独封装获取集合的函数
func getCollection(dbName, collName string) *mongo.Collection {
    return client.Database(dbName).Collection(collName)
}

// 程序退出时统一断开客户端
func cleanup() {
    if err := client.Disconnect(context.TODO()); err != nil {
        panic(err)
    }
}
  1. 修改调用函数:
func sortByName() {
    coll := getCollection("testdb", "test")
    filter := bson.D{{Key: "name", Value: "joe"}}
    opts := options.Find().SetSort(bson.D{{Key: "name", Value: 1}})
    
    cursor, err := coll.Find(context.TODO(), filter, opts)
    if err != nil {
        fmt.Printf("err in FIND: %v\n", err)
        return
    }
    defer cursor.Close(context.TODO()) // 使用完cursor后关闭,避免资源泄漏

    var results []bson.D
    err = cursor.All(context.TODO(), &results)
    if err != nil {
        fmt.Printf("err in cursor: %v\n", err)
        return
    }
    
    for _, result := range results {
        fmt.Printf("result: %v\n", result)
    }
}
  1. 在main函数中管理生命周期:
func main() {
    defer cleanup() // 程序退出时自动断开客户端
    sortByName()
}

额外注意事项

  • MongoDB客户端本身是线程安全的,无需频繁创建和断开,复用单个实例即可。
  • 必须在使用完cursor后调用cursor.Close(),避免数据库连接资源泄漏。
  • 添加客户端ping验证可以提前发现连接问题,避免后续操作报错。

内容的提问来源于stack exchange,提问作者Shakthi Thillai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:33:24