为了账号安全,请及时绑定邮箱和手机立即绑定

使用存储库模式时如何在 Go 中处理数据库连接?

使用存储库模式时如何在 Go 中处理数据库连接?

Go
GCT1015 2023-01-03 14:01:08
假设我有一个非常简单的存储库接口,它只从目标数据库读取:type UserRepository interface {    read(ctx context.Context, id WHAT_TYPE_I_SHOULD_USE_HERE) models.User}注意:请注意,在 id 参数中,我不知道用户作为 id 类型是什么,因为 id 在MongoDB基于ObjectId模式的数据库中它可能是一个UUID字段。如果有帮助,我的主数据库是 MongoDB,但我可能会切换到基于模式的数据库。现在我有一个附加到它的MongoDBRepository结构:read()type MongoDBRepository struct {}func (mo MongoDBRepository) read(ctx context.Context, id primitive.ObjectID) {    fmt.Printf("read user %s from MongoDB", id)}我有一个连接到 MongoDB 的方法:func ConnectMongoDB() (*mongo.Client, context.CancelFunc) {    client, err := mongo.NewClient(options.Client().ApplyURI(configs.MongoURI()))    if err != nil {        log.Fatal(err)    }    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)    err = client.Connect(ctx)    err = client.Ping(ctx, nil)    if err != nil {        log.Fatal(err)    }    log.Print("Successfully connected to MongoDB!")    return client, cancel}现在,随着接口的实现,我们可以为MySQL/PostgreSQL和ConnectMySQL/拥有一个类似的存储库ConnectPostgreSQL。我遇到的问题是在我的主要功能中我应该如何处理连接到我当前的数据库存储库以及如何在我的控制器中使用它来读取或更新文档/记录?当我将连接传递给控制器方法时,其类型设置为*mongo.Client如何将其抽象化,以便获取数据库连接的控制器方法未绑定到目标数据库类型?
查看完整描述

1 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

我应该如何处理连接到我当前的数据库存储库以及如何在我的控制器中使用它来读取或更新文档/记录


我一直在检查提供商文档以获取有关该问题的提示。


经过快速搜索,我在Github中找到了我需要的东西:


// Client is a handle representing a pool of connections to a MongoDB deployment. It is safe for concurrent use by

// multiple goroutines. 

客户端是线程安全的,代表的不是单个连接而是一个连接池。这意味着我可以在 Controllers/Repositories 的多个实例之间共享一个 Client 实例,并且客户端可以处理它。


从存储库开始。我们需要注入客户端:


type MongoDBRepository struct {

   Client mongo.Client

}

在当前的设计中,存储库仅包含线程安全成员,因此它本质上是线程安全的。


这是在应用程序启动代码中创建存储库的代码:


repo := &MongoDBRepository{Client: client}

在控制器中,我们定义Repository为接口类型,但我们将注入MongoDBRepository结构:


// Controller Code

type UserController struct {

   Repo UserRepository

}

控制器的启动代码也应该发生在应用程序之星上:


// App start 

controller := &UserController{Repo: repo}

要处理数据库特定类型 ( id WHAT_TYPE_I_SHOULD_USE_HERE),您需要将它们实现为泛型。它可能会使您的控制器代码变得相当复杂。考虑将这种复杂性隐藏在存储库中,并公开一些简单的东西,如字符串或 uuid。


使用这种方法,您可以轻松地在不同的数据库之间切换。您需要更改的只是应用程序初始化 ( Composition Root ) 而无需更改控制器代码。


PS 多数据库支持非常昂贵。我们已经遇到了 ID 类型的问题。将来,您应该准备好停止使用任何特定于数据库的功能,而只使用跨所有数据库可用的功能。数据库事务是 Mongo 中不可用的重要 SQL 功能之一。在完全致力于多种数据库类型之前权衡利弊。

更新:

  1. 使用 ServeHTTP(w http.ResponseWriter, r *http.Request) 方法将控制器实现为结构。

  2. main.go如果该结构如上所述,则创建实例。

  3. router.Handle使用而不是将该结构集成到路由器中router.HandleFunc

使用 struct,您应该可以更好地控制 Controller 依赖项生命周期。


查看完整回答
反对 回复 2023-01-03
  • 1 回答
  • 0 关注
  • 83 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号