Konubinix' opinionated web of thoughts

Golang Context Package

Fleeting

golang go

Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled

https://pkg.go.dev/context

Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. The Context should be the first parameter, typically named ctx:

func DoSomething(ctx context.Context, arg Arg) error { // … use ctx … }

https://pkg.go.dev/context

context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions

https://pkg.go.dev/context

same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines.

https://pkg.go.dev/context

When a request is canceled or times out, all the goroutines working on that request should exit quickly so the system can reclaim any resources they are using

https://go.dev/blog/context

context package that makes it easy to pass request-scoped values, cancellation signals, and deadlines across API boundaries to all the goroutines involved in handling a request

https://go.dev/blog/context

Background is the root of any Context tree; it is never canceled

https://go.dev/blog/context

At Google, we require that Go programmers pass a Context parameter as the first argument to every function on the call path between incoming and outgoing requests. This allows Go code developed by many different teams to interoperate well. It provides simple control over timeouts and cancellation and ensures that critical values like security credentials transit Go programs properly.

https://go.dev/blog/context

many Go APIs, especially modern ones, the first argument to functions and methods is often context.Context

https://go.dev/blog/context-and-structs

Context provides a means of transmitting deadlines, caller cancellations, and other request-scoped values across API boundaries and between processes. It is often used when a library interacts — directly or transitively — with remote servers, such as databases, APIs, and the like.

https://go.dev/blog/context-and-structs

Context makes it easy to propagate important cross-library and cross-API information down a calling stack. But, it must be used consistently and clearly in order to remain comprehensible, easy to debug, and effective.

When passed as the first argument in a method rather than stored in a struct type, users can take full advantage of its extensibility in order to build a powerful tree of cancellation, deadline, and metadata information through the call stack. And, best of all, its scope is clearly understood when it’s passed in as an argument, leading to clear comprehension and debuggability up and down the stack.

When designing an API with context, remember the advice: pass context.Context in as an argument; don’t store it in structs.

https://go.dev/blog/context-and-structs

Golang Context is a tool that is used to share request-scoped data, cancellation signals, and timeouts or deadlines across API layers or processes in a program. It is one of the most important tools while working with concurrent programming in Go

https://btree.dev/golang-context

example of request-scoped data would be the body, headers, or params of an API request

https://btree.dev/golang-context

One important point to note is cancellation doesn’t automatically stop the execution, cancel just closes the Done channel which we need to use to terminate processes

https://btree.dev/golang-context

In practical implementations, we usually work with derived contexts. We create a parent context and pass it across a layer, we derive a new context with it adding some additional information and passing it again to the next layer, and so on

https://btree.dev/golang-context

Often combined with goroutines, it simplifies data processing, cancellation, and other operations. As an interface with only four functions, time(Deadline), signal(Done), exception(error), and data(Value), it is not complicated but super-useful in different scenarios, covering almost every aspect in common usage.

https://medium.com/codex/go-context-101-ebfaf655fa95

With goroutines’ lightweight feature, it is very common for a program to enable hundreds of them, one of Go’s advantages over other high-level languages, such as Java. It is also vital in the cloud era, saving resources and being more scalable

https://medium.com/codex/go-context-101-ebfaf655fa95

how can we terminate goroutines early when we don’t need them anymore while thousands of goroutines are still in execution?

https://medium.com/codex/go-context-101-ebfaf655fa95

After creating the parent context via context.Background(), we can derive more sub-contexts from it by the four With* functions provided by the context package.

  • func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
  • func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
  • func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
  • func WithValue(parent Context, key, val interface{}) Context

https://medium.com/codex/go-context-101-ebfaf655fa95