我在这里使用半代码只是为了表明我在代码中所发生的事情的意图,而不是使问题变得复杂。
我有一个main.go文件,它调用一个连接到mongoDB数据库的方法:
mStore := store.NewMongoStore()在NewMongoStore中,我有client.Connect用来连接数据库的上下文:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()现在,在main.go中,我以这种方式将存储区传递给路由器控制器文件:
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以插入一个新文档。
正如你所看到的,在某些部分,我已经通过了上下文,而在某些部分,我没有。我真的不知道该怎么办?使用上下文的正确方法是什么?我应该总是在周围传递上下文,或者创建这样的新上下文是完全可以的,而不是在方法参数中传递上下文。
--这种编码的最佳实践是什么?从性能的角度来看,哪一个更好?
发布于 2022-07-19 09:57:28
对于我自己的问题,我找到了一个有趣的答案,所以如果有同样的问题,我宁愿在这里为未来的用户提供。
如果我传递与userController连接到Mongo的相同上下文,并将其进一步传递给CreateUser函数:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)注意:,而不是取消NewMongoStore函数i中的上下文,而是在main函数中取消上下文。
10秒后,如果您调用POST /users,您将得到context deadline exceeded,因此基本上您不能使用这个上下文来做其他事情,您必须在每个CreateUser调用上创建新的上下文。
所以我写的很好。在我的示例中,我等待10秒才连接到mongo,对于insert操作上下文则等待1秒。
发布于 2022-07-17 08:59:32
根据我的经验,Context有两个主要的用例:
request_id,并将其传递到代码的最低部分,并记录这个request_id以在整个代码库中执行错误跟踪。context.Background应该足够好。Context的这些信息。但是大多数具有Context参数的第三方和标准库都可以很好地处理这两个特性(例如数据库库、HTTP库)。有了这个特性,一旦Context失效,您就可以自动回收资源。context.Background(),以避免这些写入在上游上下文被取消后被取消。context.还会清除信息上下文,因此有时您需要从上游上下文中提取上下文信息,并将它们手动添加到这个新的context.Background()中。
强迫所有函数都使用Context参数有点过分(向简单的greatestCommonDivisor函数添加Context是没有意义的),但是将Context参数添加到任何您需要的地方都是没有坏处的。Context具有足够好的性能,对于您的用例(HTTP和数据库编写)来说,它不应该给您的服务造成可见的开销。
https://stackoverflow.com/questions/73010023
复制相似问题