What is Context in Golang

Context – is Golang package including struct Context and helping functions.

The main idea of the package – to control execution time of network requests (HTTP, TCP and etc.) to prevent infinite waiting or program blocking if the operation takes too much time.

You will be able to set up request timeout using context:

context.WithTimeout (function is wrapper on context.WithDeadline)

or cancel request by a condition:

context.WithCancel()

Cancel request by timeout

  • Analogy from real life: You call a friend and wait for them to answer. Typically, you wait for some time during which they should pick up the call, for example, 20 seconds. If they still haven’t answered by then, you cancel the call.
  • Real-world example: A script fetches data from an external service via an API on a daily basis. The task is to terminate the API request if it hasn’t been completed within 20 seconds.

The function context.Background() is also using in the next example. It returns empty context (it’s usually used to initialize contexts).

Code example:

// it creates context with timeout, where the first argument is parent context, the second is timeout in seconds.
ctx, cancel := context.WithTimeout(context.Background(), 20 * time.Second)
defer cancel()

// it creates new request using context.
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "<api_url>", nil)
if err != nil {
	return nil, fmt.Errorf("failed to create request with ctx: %w", err)
}

// send request.
res, err := http.DefaultClient.Do(req)
if err != nil {
	return nil, fmt.Errorf("failed to perform http request: %w", err)
}

return res, nil

Cancel request by condition

  • Real-life scenario: imagine you’re a school student struggling with a math problem. You turn to your parents and your sister for help. Mom, dad, and your sister start working on the problem, and your sister solves it first. Consequently, you tell your parents that there’s no need to solve the problem anymore because your sister has already figured it out.
  • Real-world task: a script is searching for the fastest-responding server. It sends requests to 10 different servers simultaneously. When it receives the first response, it cancels all the remaining requests.

Code example:

	var servers = []string{"<SERVER_URL_1>", "<SERVER_URL_2>", "<SERVER_URL_3>"}
	var wg sync.WaitGroup

	// it creates context, where the argument is parent context.
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// iterates over servers and looking for the fastest one.
	for _, url := range servers {
		wg.Add(1)
		go func() {
			// it creates new request using context.
			req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
			if err != nil {
				fmt.Errorf("failed to create request with ctx: %w", err)
			}

			// Sends request.
			_, err = http.DefaultClient.Do(req)
			if err != nil {
				fmt.Errorf("failed to perform http request: %w", err)
			}
			wg.Done()

			// The script has got response, so cancel context. Rest of the requests will be cancelled at this moment.
			cancel()
		}()
	}
	wg.Wait()

.....

go func() {
			for {
				select {
				case <-ctx.Done():
                // We got here when the fastest server was found.
					return
				}
			}
		}()

Video tutorial about Golang context:

You might also like



Leave a Comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.