{}const=>[]async()letfn</>var
Development

Go-contexts without pain — how to understand context.Context and why it is everywhere

Let's analyze why context.Context is found in almost every Go function, how it saves from freezes and manages the lifetime of operations.

К

Kodik

Author

3 min read

Go-developers quickly get used to the syntax: functions, interfaces, errors. But almost immediately after "Hello, world", something mysterious begins to appear in the code — context.Context. And not just somewhere in the depths of the package, but right in the signature of every second function. Why is it needed and why is it indispensable?

Let's find out.

What is context in Go

context.Context is a special object that is passed along the call chain and controls:

  • the lifetime of operations,

  • cancellation of processes,

  • deadlines,

  • transfer of metadata (for example, request ID).

Context is like an "invisible backpack" that a function receives with a call and from which you can get useful information.

🔥 100,000+ students already with us

Tired of reading theory?
Time to code!

Kodik — an app where you learn to code through practice. AI mentor, interactive lessons, real projects.

🤖 AI 24/7
🎓 Certificates
💰 Free
🚀 Start learning
Joined today

Where context is most often found

  1. Working with network requests — cancellation by timeout if the response does not arrive for too long.

  2. Queries to the database — to avoid keeping the connection "hanging" indefinitely.

  3. Background flames — graceful shutdown when the service is completed.

Why is it in almost every argument

Go adheres to the principle: explicit is better than implicit. Instead of global variables or hidden signals, functions directly receive context. This makes the code predictable and gives control at the top level — where the request starts.

func fetchUser(ctx context.Context, id int) (User, error) {
    row := db.QueryRowContext(ctx, "SELECT name FROM users WHERE id=?", id)
    ...
}

If the request is set ctx with a timeout, then any operation inside will automatically stop after the time has elapsed.

Important work techniques

Creating a context with a timeout:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

Manual cancellation:

ctx, cancel := context.WithCancel(context.Background())
go func() {
    time.Sleep(time.Second)
    cancel() // stop the work of everyone who listens to this ctx
}()

Transfer of values (carefully!):

ctx = context.WithValue(ctx, "requestID", "abc123")

Important: abuse WithValue is not worth it — it is more like "metadata" than full-fledged data.

Typical mistakes and pitfalls

  • Did not call cancel() → resource leak.

  • We put everything in WithValue → readability is lost.

  • We do not pass the context further → we deprive the function of the ability to control itself.

The main idea of context is simple: the control should be at the calling code, not at the called code. That's why in Go almost every public function in the standard library package starts with the argument ctx.

Context is not just a buzzword in Go. It is a built-in tool that makes your programs predictable, manageable, and protected from freezes. The sooner you start using it correctly, the less "pain" you will have in the future.

Codica has new top course on Go 🚀
This is a powerful and clear start for those who want to master the language in which fast and reliable services are written. In the course, we explain everything in simple words: from the first steps to serious concepts like goroutines and contexts.

And we also have a cozy Telegram channel, where we share news from the IT world, analyze interesting tasks and communicate with the community. Subscribe to not miss the most important things.

🎯Stop procrastinating

Liked the article?
Time to practice!

In Kodik, you don't just read — you write code immediately. Theory + practice = real skills.

Instant practice
🧠AI explains code
🏆Certificate

No registration • No card