假设我有一个非常简单的存储库界面,只从目标数据库读取:

type UserRepository interface {
    read(ctx context.Context, id WHAT_TYPE_I_SHOULD_USE_HERE) models.User
}

NOTE:注意,在id参数中,我不知道用户应该使用什么,因为MongoDB中的id类型是ObjectId,而在基于模式的数据库中,它可能是UUID字段.如果有帮助的话,我的主要数据库是MongoDB,但我可能会切换到基于模式的数据库.

现在我有一个MongoDBRepository struct ,它有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/PostgreSQLConnectMySQL/ConnectPostgreSQL创建一个类似的存储库.

我的主要功能是如何处理连接到当前数据库存储库的问题,以及如何在控制器中使用它来读取或更新文档/记录?

当我将连接传递给一个控制器方法时,它的类型设置为*mongo.Client.我如何将其抽象出来,使我获得DB连接的控制器方法不绑定到目标DB类型?

推荐答案

我应该如何处理连接到当前数据库存储库和

我总是判断提供者文档以获得关于该问题的提示.

快速搜索后,我在Github中找到了我需要的:

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

客户端是线程安全的,它代表的不是单个连接,而是一个连接池.这意味着我可以在控制器/存储库的多个实例之间共享一个客户端实例,客户端可以处理这个问题.

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

type MongoDBRepository struct {
   Client mongo.Client
}

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

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

repo := &MongoDBRepository{Client: client}

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

// Controller Code
type UserController struct {
   Repo UserRepository
}

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

// App start 
controller := &UserController{Repo: repo}

要处理特定于db的类型(id WHAT_TYPE_I_SHOULD_USE_HERE),需要将其实现为Generics.这可能会让你的控制器代码变得相当复杂.考虑将这种复杂性隐藏在存储库中,并公开一些简单的东西,如字符串或uuid.

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

P、 在美国,支持多个数据库相当昂贵.我们已经面临ID类型的问题.在future ,你应该准备好stop using any DB specific features and use only features available across all the databases.DB事务是Mongo中不可用的强大SQL功能之一.在您完全致力于多种DB类型之前,权衡利弊.

更新:

  1. 使用ServeHTTP(w http.ResponseWriter,r*http.Request)方法将控制器实现为 struct .
  2. 如果该 struct 如上所述在main.go中创建实例.
  3. 使用router.Handle而不是router.HandleFunc将该 struct 集成到路由中

使用struct,您应该能够更好地控制控制器依赖项的生命周期.

Sql相关问答推荐

SQL Google Sheets:UNIQUE/DISTINCT和编码查询函数

Select /过滤postgr中的树 struct

SQL—如何在搜索的元素之后和之前获取元素?

Postgres JSONB对象筛选

出现5次后,将所有正斜杠替换为连字符

Stack Exchange站点上的最短帖子(按正文长度计算,用户名为原始发帖(SEDE))

LEFT JOIN不显示计数0我期望的方式

带上最后日期(结果)

在Postgres中合并相似的表

Oracle中的时间戳

将两列相加为同一表中的行的查询

需要从键-值对数据中提取值

同时插入和更新记录

Postgresql - WHERE 中的 MAX 标准 - 初学者问题

按行值出现的顺序对行值进行分组

通过ID和数据找到每个不同的值

当 2 列具有静态值并且第 3 列使用运算符 IN 时,对 PostgreSQL 和 3 列上的复杂索引的最佳查询

批量更改WooCommerce中所有产品的税收状态

BigQuery Pivot 遗漏行

在 SQL 的每行选项中 Select 最大值