首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我应该在Go中将context.Context传递给底层DB方法吗?

我应该在Go中将context.Context传递给底层DB方法吗?
EN

Stack Overflow用户
提问于 2022-07-17 07:44:17
回答 2查看 246关注 0票数 0

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

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

代码语言:javascript
复制
mStore := store.NewMongoStore()

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

代码语言:javascript
复制
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

现在,在main.go中,我以这种方式将存储区传递给路由器控制器文件:

代码语言:javascript
复制
routes.GenericRoute(router, mStore)

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

代码语言:javascript
复制
func GenericRoute(router *gin.Engine, mStore store.Store) {
    router.POST("/users", controllers.CreateUser(mStore))
}

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

代码语言:javascript
复制
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

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

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

正如你所看到的,在某些部分,我已经通过了上下文,而在某些部分,我没有。我真的不知道该怎么办?使用上下文的正确方法是什么?我应该总是在周围传递上下文,或者创建这样的新上下文是完全可以的,而不是在方法参数中传递上下文。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-19 09:57:28

对于我自己的问题,我找到了一个有趣的答案,所以如果有同样的问题,我宁愿在这里为未来的用户提供。

如果我传递与userController连接到Mongo的相同上下文,并将其进一步传递给CreateUser函数:

代码语言:javascript
复制
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)

注意:,而不是取消NewMongoStore函数i中的上下文,而是在main函数中取消上下文。

10秒后,如果您调用POST /users,您将得到context deadline exceeded,因此基本上您不能使用这个上下文来做其他事情,您必须在每个CreateUser调用上创建新的上下文。

所以我写的很好。在我的示例中,我等待10秒才连接到mongo,对于insert操作上下文则等待1秒。

票数 0
EN

Stack Overflow用户

发布于 2022-07-17 08:59:32

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

  1. 传递信息。对于您的问题,您可能希望为每个请求生成一个request_id,并将其传递到代码的最低部分,并记录这个request_id以在整个代码库中执行错误跟踪。
    1. 这个特性并不总是有用的,例如,您希望初始化一个MongoDB连接,但它是在服务启动期间完成的。此时没有有意义的上下文,带有超时的context.Background应该足够好。

  1. Auto-cancellation和超时值。这两个特性并非凭空而来,您需要调优代码以处理来自Context的这些信息。但是大多数具有Context参数的第三方和标准库都可以很好地处理这两个特性(例如数据库库、HTTP库)。有了这个特性,一旦Context失效,您就可以自动回收资源。
    1. 有时您会想要停止这种级联行为,例如在后台写日志,然后您需要创建一个新的context.Background(),以避免这些写入在上游上下文被取消后被取消。context.

还会清除信息上下文,因此有时您需要从上游上下文中提取上下文信息,并将它们手动添加到这个新的context.Background()中。

强迫所有函数都使用Context参数有点过分(向简单的greatestCommonDivisor函数添加Context是没有意义的),但是将Context参数添加到任何您需要的地方都是没有坏处的。Context具有足够好的性能,对于您的用例(HTTP和数据库编写)来说,它不应该给您的服务造成可见的开销。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73010023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档