首页 > 解决方案 > 如何正确断开 MongoDB 客户端

问题描述

据我了解,您必须在使用完 MongoDB 后断开与它的连接,但我不完全确定如何正确操作

var collection *mongo.Collection
var ctx = context.TODO()

func init() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017/")
    client, err := mongo.Connect(ctx, clientOptions)
    if err != nil {
        log.Fatal(err)
    }
    //defer client.Disconnect(ctx)

    err = client.Ping(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Connected successfully")

    collection = client.Database("testDB").Collection("testCollection") //create DB
}

有注释掉的函数调用 defer client.Disconnect(ctx) ,如果所有代码都发生在 main() 函数中,这将正常工作,但由于在 init() 执行后立即调用 defer,因此 main() 函数中的 DB 已经断开连接。

所以问题是——处理这个案子的正确方法是什么?

标签: mongodbgo

解决方案


您的应用程序需要在所有服务或存储库中连接 MongoDB 客户端,因此如果您在应用程序包中分离了 MongoDB 客户端连接和断开功能,则更容易。您不需要连接 MongoDB 客户端,如果您的服务器正在启动,如果您的服务或存储库需要 MongoDB 客户端连接,您可以先连接。

// db.go
package application

import (
    "context"
    "fmt"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "log"
    "os"
)

var client *mongo.Client

func ResolveClientDB() *mongo.Client {
    if client != nil {
        return client
    }

    var err error
    // TODO add to your .env.yml or .config.yml MONGODB_URI: mongodb://localhost:27017
    clientOptions := options.Client().ApplyURI(os.Getenv("MONGODB_URI"))
    client, err = mongo.Connect(context.Background(), clientOptions)
    if err != nil {
        log.Fatal(err)
    }

    // check the connection
    err = client.Ping(context.Background(), nil)
    if err != nil {
        log.Fatal(err)
    }

    // TODO optional you can log your connected MongoDB client
    return client
}

func CloseClientDB() {
    if client == nil {
        return
    }

    err := client.Disconnect(context.TODO())
    if err != nil {
        log.Fatal(err)
    }

    // TODO optional you can log your closed MongoDB client
    fmt.Println("Connection to MongoDB closed.")
}

主要:

func main() {
    // TODO add your main code here
    defer application.CloseClientDB()
}

在您的存储库或服务中,您现在可以轻松获得 MongoDB 客户端:

// account_repository.go

// TODO add here your account repository interface
func (repository *accountRepository) getClient() *mongo.Client {
    if repository.client != nil {
        return repository.client
    }
    repository.client = application.ResolveClientDB()
    return repository.client
}

func (repository *accountRepository) FindOneByFilter(filter bson.D) (*model.Account, error) {
    var account *model.Account
    collection := repository.getClient().Database("yourDB").Collection("account")
    err := collection.FindOne(context.Background(), filter).Decode(&account)
    return account, err
}

推荐阅读