如何在Golang中跨包管理MongoDB客户端

4

我目前在使用GoLangMongoDB,这是我的当前使用场景。

我希望在特定的包中初始化连接到MongoDB数据库,并在其他几个本地包中使用返回的client。以下是我尝试的方法,

我已经在名为dataLayer的包中初始化了对MongoDB的连接,如下所示:

package dataLayer

import (
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
)

func InitDataLayer() {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI(credentials.MONGO_DB_ATLAS_URI))
    if err != nil {
        log.Fatal(err)
    } else {
        log.Println("Connected to Database")
    }
}

现在,如果我希望在其他包中使用返回的client,反复调用initDataLayer以获得client是否安全合适生产环境?

非常感谢。

1个回答

17

你不需要一遍又一遍地调用InitDataLayer。你只需要创建一个客户端,就可以在多个位置使用同一个客户端连接到Mongo DB。

Mongo客户端在内部维护了一个连接池,因此你不需要一遍又一遍地创建这个客户端。

将该客户端作为结构字段存储并保持重复使用是一个好的设计。

编辑:

创建连接

package dataLayer

import (
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
)

func InitDataLayer()(*mongo.Client) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI(credentials.MONGO_DB_ATLAS_URI))
    if err != nil {
        log.Fatal(err)
    } else {
        log.Println("Connected to Database")
    }
    return client
}

main.go,

在使用完毕后关闭连接,否则连接将被泄露。

func main(){
   //...
   client = dataLayer.InitDataLayer()
   defer client.Disconnect(context.Background())
   ...
}

存储客户端在存储库结构中的Repository/DAL

接口

type BookRepository interface {
   FindById( ctx context.Context, id int) (*Book, error)
}

存储客户端信息于结构体中的仓库实现

type bookRepository struct {
  client *mongo.Client
}

func (r *bookRepository) FindById( ctx context.Context, id int) (*Book, error) {
  var book  Book
  err := r.client.DefaultDatabase().Collection("books").FindOne(ctx, bson.M{"_id": id }).Decode(&book)
  
  if err == mongo.ErrNoDocuments {
    return nil, nil
  }
  if err != nil  {
     return nil, err
  }
  return &book, nil
}

@sonus21,感谢您的回复。你能展示一个例子吗? - mekings
你可以使用依赖注入的概念。 - Misti
@Misti 这是真的,但Go语言并没有完全支持依赖注入。虽然人们已经为DI创建了库,但我们需要一个支持清理的DI,同时它不应该创建太多Client实例。 - sonus21
上下文呢?应该放在存储库结构体里吗? - DenCowboy
@DenCowboy 并没有固定的上下文,它是动态的,每次调用都应该作为函数参数传递。 - sonus21

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接