首页 >后端开发 >Golang >Golang cli 应用程序 - 如何正确使用上下文?

Golang cli 应用程序 - 如何正确使用上下文?

WBOY
WBOY转载
2024-02-09 10:42:20966浏览

Golang cli 应用程序 - 如何正确使用上下文?

Golang cli 应用程序 - 如何正确使用上下文?php小编鱼仔将为您介绍如何在Golang的cli应用程序中正确使用上下文。在开发cli应用程序时,上下文是非常重要的,它可以帮助我们管理应用程序的状态、传递参数和错误等。本文将详细解释上下文的概念,并给出一些实际应用的示例,帮助您更好地理解和运用上下文。无论您是初学者还是有一定经验的开发者,本文都将对您有所帮助。让我们一起来深入了解Golang cli应用程序中的上下文吧!

问题内容

我是 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")
}

解决方法

如果你仔细想想,context.context 可以“水平”共享(意思是在不属于同一调用堆栈的操作之间)是没有意义的。 golang context 提供了要执行操作(包括调用堆栈中其下方的任何嵌套操作)的上下文 - 例如“在 x 秒内”,以防止由于通信延迟等而挂起。因此,如果您发出并行 10 个请求,您应该为每个请求提供自己的上下文 - 您可能不希望第十个请求失败,因为第一个请求失败了。如果您只是使用 context.background()context.todo(),没有进一步的装饰,您可能不需要在第一次创建它时将 context 存储在变量中 - 您可以在创建时创建将其传递给调用堆栈中的第一个函数,正确构造的代码将根据需要将其向下传递到堆栈,并一路应用必要的修饰:

func Execute() {
  DoThing(context.Background())
  // Other stuff
}

func DoThing(pctx context.Context) {
  ctx, cancel := context.WithTimeout(pctx, 10 * time.Second) // Timeout after 10 seconds
  defer cancel()

  DoThingThatMayTakeAWhile(ctx)
  select {
    // You may want other stuff here
    case <-ctx.Done():
      // Context timed out, maybe log an error?
  }
}

func DoThingThatMayTakeAWhile(pctx context.Context) {
  DoThingNeedingInfoInContext(context.WithValue(pctx, "thisisakey", "value"))
}

func DoThingNeedingInfoInContext(ctx context.Context) {
  val := ctx.Value("thisisakey")
  // Do something with val, check that it isn't nil, etc.
}
  

如果我要多次调用 dothingthatmaytakeawhile(),我想为每个调用提供一个单独的子上下文 - 我希望与每个调用共享 ctx。 p>

因此,在您的代码中,每次调用 mongo.connect() 都应该收到一个新创建的 context.context 实例。

以上是Golang cli 应用程序 - 如何正确使用上下文?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除