猿问

重用 mongodb 连接时处理上下文

我通过作为参数传递来使多个 goroutine 共享单个连接。client


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


慕斯709654
浏览 102回答 2
2回答

慕虎7371278

这取决于您的和方法的行为方式。让我们想象一下,该方法是一个简单的短命goroutine,它对DB进行一个查询,您唯一想要的就是检查其父上下文是否为“完成”或“取消”。然后,您可以为 Foo 方法提供父上下文。FooBarFoofunc main() {&nbsp; &nbsp; uri := "mongodb://localhost:27017"&nbsp; &nbsp; ctx := context.Background()&nbsp; &nbsp; client, err := Connect(ctx, uri)&nbsp; &nbsp; ctx, cancel := context.WithCancel(ctx)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; go Foo(ctx, client)&nbsp; &nbsp; go Bar(context.WithValue(ctx, "uri", uri), client)&nbsp; &nbsp; // cancel parent context&nbsp; &nbsp; cancel()&nbsp; &nbsp; time.Sleep(5*time.Second)}func Foo(ctx context.Context, client *Client) {&nbsp; &nbsp; fmt.Printf("Foo: %s\n", ctx.Value("uri"))&nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <- ctx.Done():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err := ctx.Err()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // you could switch for the actual reason&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("In our case context canceled: ", err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Do something...")&nbsp; &nbsp; }}另一方面,如果执行一些重要的逻辑并对 DB 进行多次调用,您可能希望一个单独的上下文能够将其与父上下文分开取消。然后,您可以从父母那里获得新的上下文。Barfunc Bar(ctx context.Context, client *Client) {&nbsp; &nbsp; // Bar has a non trivial logic and needs a separate cancellation and handling&nbsp; &nbsp; ctx, cancelFunc := context.WithCancel(ctx)&nbsp; &nbsp; fmt.Printf("Bar: %s\n", ctx.Value("uri"))&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // cancel derived context&nbsp; &nbsp; cancelFunc()}

慕侠2389804

我也这样做过type DB struct {&nbsp; &nbsp; client *mongo.Client}func (db *DB) GetVideoStream {}func main() {&nbsp; &nbsp; ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)&nbsp; &nbsp; client, err := mongo.Connect(ctx, clientOpts)&nbsp; &nbsp; db := &DB{client: client}&nbsp; &nbsp; go db.GetVideoStream()&nbsp; &nbsp; http.HandleFunc("/api/", db.GetVideoStream)}您可以使用指针接收器来执行相同的操作。我是新来的,还是该语言的新手
随时随地看视频慕课网APP

相关分类

Go
我要回答