mongodb - 我应该将 context.Context 传递给 Go 中的底层数据库方法吗?

标签 mongodb go go-context

我在这里使用半代码只是为了表明我对代码中发生的事情的意图,而不是使问题中的事情复杂化。

我有一个 main.go 文件,它调用连接到 mongoDB 数据库的方法:

mStore := store.NewMongoStore()

NewMongoStore 中,我有 client.Connect 用于连接数据库的上下文:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

现在在 main.go 中,我通过这种方式将存储传递到我的路由器 Controller 文件:

routes.GenericRoute(router, mStore)

GenericRoute 中,我获取 mStore 并将其传递给函数处理程序:

func GenericRoute(router *gin.Engine, mStore store.Store) {
    router.POST("/users", controllers.CreateUser(mStore))
}

现在在 CreateUser 中,我再次创建一个上下文,如下所示,将文档插入到 MongoDB 中:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

insertedId, err := repo.CreateUser(ctx, newUser{"John", "Doe"})

在这里,我将上下文传递给 createUser 以插入新文档。

正如你所看到的,在某些部分我已经传递了上下文,而在某些部分我没有。我真的不知道我应该做什么?处理上下文的正确方法是什么?我是否应该始终传递上下文,或者创建像这样的新上下文而不在方法参数中传递上下文是完全可以的。

这种编码的最佳实践是什么?从性能角度来看,哪一个更好?

最佳答案

根据我的经验,Context 有两个主要用例:

  1. 传递信息。对于您的问题,您可能希望为每个请求生成一个 request_id 并将其传递到代码的最低部分,并记录此 request_id 以跨整个请求进行错误跟踪整个代码库。
    1. 此功能并不总是有用,例如您想要初始化 MongoDB 连接,但它是在服务启动期间完成的。此时没有有意义的上下文,带有超时的 context.Background 应该足够了。
    2. 谨慎对待从 Context 检索的值的变化,如果您到处传递 Context,这可能会导致并发访问。
  2. 自动取消和超时。这两个功能并非凭空而来,您需要调整代码以处理 Context 中的这些信息。但大多数带有 Context 参数的第三方库和标准库都可以很好地处理这两个功能(例如数据库库、HTTP 调用库)。使用此功能,您可以在 Context 失效后自动回收资源。
    1. 有时你会想要停止这种级联行为,例如在后台 goroutine 中写入日志,那么你需要创建一个新的 context.Background() 以避免这些写入在上游被取消上下文已取消。 context.Background() 还会清除信息上下文,因此有时您需要从上游上下文中提取上下文信息,并手动将它们附加到这个新上下文中。

对所有函数强制使用 Context 参数有点过分了(没有必要将 Context 添加到简单的 greatestCommonDivisor 函数)但是在您需要的任何地方添加 Context 参数永远不会有什么坏处。 Context 具有足够好的性能,对于您的用例(HTTP 服务器和数据库写入),它不应该对您的服务造成可见的开销。

关于mongodb - 我应该将 context.Context 传递给 Go 中的底层数据库方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73010023/

相关文章:

multithreading - 防止上下文取消在业务逻辑中间停止函数执行

node.js - 我的文档在 NodeJS 的 mongodb 中没有被删除

ruby-on-rails - 如何在 mongoid/rails 中获取一个字段?

go - const复合文字去吗?

go - Golang客户端库对Apache Airflow的支持

Go模板和函数

go - 如何将上下文值从 Gin 中间件传播到 gqlgen 解析器?

mongodb - 在 mongoDB 官方 docker 镜像中创建数据库和用户

mongodb - Meteor 方法与拒绝/允许规则