我是golang的新手,对上下文和如何在golang应用程序中使用上下文有些困惑,特别是我正在使用cli应用程序,只需要访问mongo。
就像-我只是创建了一个共享ctx上下文变量,然后将其用于需要上下文的任何操作,这对吗?
任何需要上下文的操作会重新启动5秒计时器吗?或者这是一个共享计时器?
package main
import (
"context"
"log"
"os"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
func main() {
log.SetOutput(os.Stdout)
// Create a context with a timeout of 5 seconds
//This defines a timeout context that will be canceled after 5 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// always defer in case func returns early
defer cancel()
//Creates a new ClientOptions instance.
clientOptions := options.Client()
clientOptions = clientOptions.ApplyURI("mongodb+srv://127.0.0.1?retryWrites=true&w=majority")
//Connect to mongo
client, err := mongo.Connect(ctx, clientOptions)
defer client.Disconnect(ctx)
if err != nil {
log.Fatal(err)
}
//Test connection to the database
log.Println("I: test mongo connection using ping")
err = client.Ping(ctx, readpref.Primary())
if err != nil {
log.Fatal(err)
}
log.Println("I: Fin")
}
2条答案
按热度按时间uqdfh47h1#
如果您仔细考虑一下,就会发现“水平”共享
context.Context
是没有意义的(意味着不属于同一调用堆栈的操作之间)。golangContext
提供了操作(包括调用栈中在其下的任何嵌套操作)要被执行-诸如“在X秒内”,以防止由于通信延迟而挂起,所以如果你并行发出10个请求,你应该给每个请求一个自己的上下文-你可能不希望第十个请求失败,因为第一个失败了。如果你只是使用context.Background()
或context.TODO()
,没有进一步的修饰,你可能不需要在你第一次创建Context
的时候把它存储在一个变量中--你可以在把它传递给调用栈中的第一个函数的时候创建它,并且适当构造的代码将适当地将其向下传递到堆栈,在此过程中应用必要的修饰:如果我要对
DoThingThatMayTakeAWhile()
进行多次调用,我希望给每个调用一个单独的子上下文--我不希望与每个调用共享ctx
。因此,在 * 您的 * 代码中,对
mongo.Connect()
的每个调用都应该接收一个新创建的context.Context
示例。yqyhoc1h2#
为每个需要上下文的操作创建一个新的上下文变量,上下文的计时器将永远不会重新启动。
在您的示例中,尝试在
context.WithTimeout
之后添加time.Sleep(6*time.Second)
,您将看到所有操作都返回错误context deadline exceeded
。