mongodb - 重用 mongodb 连接时处理上下文
问题描述
我通过client
作为参数传递使多个 goroutine 共享一个连接。
uri := "mongodb://localhost:27017"
ctx := context.Background()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
go Foo(client)
go Bar(client)
func Foo(client *mongo.Client) {
// ...
}
func Bar(client *mongoClient) {
// ...
}
我对如何处理感到困惑ctx
。我应该在每次查询数据库时创建一个新的上下文,还是应该像客户端一样重用上下文?
解决方案
这取决于您Foo
和Bar
方法的行为方式。让我们假设该Foo
方法是一个简单的短期 goroutine,它对 DB 进行一次查询,而您唯一需要做的就是检查其父上下文是否未完成或已取消。然后你可以为你的 Foo 方法提供父上下文。
func main() {
uri := "mongodb://localhost:27017"
ctx := context.Background()
client, err := Connect(ctx, uri)
ctx, cancel := context.WithCancel(ctx)
if err != nil {
panic(err)
}
go Foo(ctx, client)
go Bar(context.WithValue(ctx, "uri", uri), client)
// cancel parent context
cancel()
time.Sleep(5*time.Second)
}
func Foo(ctx context.Context, client *Client) {
fmt.Printf("Foo: %s\n", ctx.Value("uri"))
select {
case <- ctx.Done():
err := ctx.Err()
if err != nil {
// you could switch for the actual reason
fmt.Println("In our case context canceled: ", err)
return
}
fmt.Printf("Do something...")
}
}
另一方面,如果Bar
执行一些重要的逻辑并对 DB 进行多次调用,您可能希望单独的上下文能够与父上下文分开取消它。然后你可以从你的父母那里得到一个新的背景。
func Bar(ctx context.Context, client *Client) {
// Bar has a non trivial logic and needs a separate cancellation and handling
ctx, cancelFunc := context.WithCancel(ctx)
fmt.Printf("Bar: %s\n", ctx.Value("uri"))
// cancel derived context
cancelFunc()
}
推荐阅读
- ios - 如何将二维数组填充到 CollectionView 上?
- angularjs - 过滤后如何更改分页,而不是在页面上寻找结果?
- bootstrap-4 - 下拉在php中bootstrap4的动态导航栏中不起作用
- git - TFS 2017/GIT - 拉取请求有冲突,如何在没有 VS2017 团队资源管理器的情况下编辑/解决它们?
- python - 将第一个列表 [] 中的每个值迭代到另一个列表 [] 上以形成字典 {}
- r - 如何根据范围拆分数据
- sql - 如何将 csv 文件作为参数传递给 sql 脚本?
- python - 在一个查询中获取由 ForeignKey 分层嵌套的所有对象
- javascript - 导入/更改 HTML 内容(在 ES6 更新后)
- google-api - Google+ 登录 API 关闭 - Profile.me