Essential Go  Suggest an edit

Context

Package context in standard library provides type Context which is hard to explain because it has multiple uses.

Here are the most common uses of context.Context:

Creating a context

In most cases you’ll be calling existing API that requires context.Context.

If you don’t have one, use context.TODO() or context.Background() functions to create it. Read about the difference.

context.Context is an immutable (read-only) value so you can’t modify it.

To create e.g. a context with value, you call context.WithValue() which returns a new context that wraps existing context and adds additional information.

context.Context is an interface so you could pass nil but it’s not recommended.

Many APIs expect non-nil value and will crash if passed nil so it’s best to always pass one created with context.Background() or context.TODO().

There is no performance issue because those functions return shared, global variables (yay immutability!).

Using context with timeout to set timeout for HTTP requests

Repeating an example from HTTP client article here’s a way to create a context with timeout to ensure HTTP GET request doesn’t hang forever:

uri := "https://httpbin.org/delay/3"
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
	log.Fatalf("http.NewRequest() failed with '%s'\n", err)
}

ctx, _ := context.WithTimeout(context.TODO(), time.Millisecond*100)
req = req.WithContext(ctx)

resp, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
	log.Fatalf("http.DefaultClient.Do() failed with:\n'%s'\n", err)
}
defer resp.Body.Close()
2018/10/18 02:24:52 http.DefaultClient.Do() failed with:
'Get https://httpbin.org/delay/3: context deadline exceeded'
exit status 1

HTTP client knows how to interpret context with a timeout. You just need to create and provide it.

  ↑ ↓ to navigate     ↵ to select     Esc to close