𝗚𝗼 𝗖𝗼𝗻𝘁𝗲𝘅𝘁 𝗣𝗮𝗰𝗸𝗮𝗴𝗲
Most Go developers use context.Context without understanding it. You see it in HTTP handlers, database calls, and SDK methods. Many beginners pass context.Background() everywhere.
This mistake causes problems. A Lambda function might hang past its timeout. A database query might keep running after a user disconnects.
Context allows you to send cancellation signals and deadlines through your code. It helps you answer three questions:
• Should this operation continue running? • When must this operation finish? • What request data flows with this call?
The Context interface has four methods:
- Deadline(): Returns when the context will cancel.
- Done(): Returns a channel that closes when the context cancels. Use this in select statements to stop work.
- Err(): Returns why the context stopped (DeadlineExceeded or Canceled).
- Value(): Retrieves request-scoped data like a Trace ID.
Context works as a tree. You start with a parent context and create children.
Root Contexts:
- context.Background(): Use this at the start of your program.
- context.TODO(): Use this as a placeholder during refactoring.
Child Contexts:
- context.WithCancel(): Allows you to stop work manually.
- context.WithTimeout(): Stops work after a specific duration.
- context.WithDeadline(): Stops work at a specific time.
- context.WithValue(): Passes metadata like User IDs.
Crucial Rule: Always call the cancel function. Use defer cancel() immediately after creating a child context. If you skip this, you create memory leaks.
Best Practices:
- Pass context as the first argument to functions.
- Do not store context in structs.
- Use context.WithValue only for metadata, not for dependencies like database clients.
- Check ctx.Err() inside long loops to exit early.
- Use custom types for context keys to avoid collisions.
When a parent context cancels, all its children cancel automatically. This makes it easy to stop an entire chain of operations across your whole system.