Home  >  Article  >  Backend Development  >  Golang cli application - how to use context correctly?

Golang cli application - how to use context correctly?

WBOY
WBOYforward
2024-02-09 10:42:20907browse

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

Golang cli application - how to use context correctly? PHP editor Yuzai will introduce you how to use context correctly in Golang's cli application. When developing cli applications, context is very important, it can help us manage the state of the application, pass parameters and errors, etc. This article will explain the concept of context in detail and give some practical application examples to help you better understand and apply context. Whether you are a beginner or an experienced developer, this article will help you. Let’s dive into the context in a Golang cli application!

Question content

I am new to golang and a little confused about context and how to use context in golang application. Specifically, I'm developing a cli application that only needs access to mongo, for example.

Like - I just create a single shared ctx context variable and then use it for any action that requires context, is this correct?

Will any operation that requires context restart the 5-second timer? Or is this a shared timer?

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

Workaround

If you think about it, context.context can be shared "horizontally" (meaning between operations that do not belong to the same call stack) Yes meaningless. golang context provides the context in which the operation is to be performed (including any nested operations below it in the call stack) - e.g. "within x seconds", to prevent hangs due to communication delays etc. So if you make 10 requests in parallel, you should give each request its own context - you probably don't want the tenth request to fail because the first failed. If you're just using context.background() or context.todo() without further decoration, you probably don't need to add context# when you first create it ## Stored in a variable - you can create it at creation time by passing it to the first function in the call stack, properly constructed code will pass it down the stack as needed, applying the necessary decorations along the way:

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.
}
  

If I were to call

dothingthatmaytakeawhile() multiple times, I'd like to have a separate subcontext for each call - I don't want to share the ctx with each call . p> Therefore, in

your code, each call to mongo.connect() should receive a newly created context.context instance.

The above is the detailed content of Golang cli application - how to use context correctly?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete
Previous article:Golang multiple jsonNext article:Golang multiple json