Skip to Content
Go Realm v1 is released 🎉
Go RoutinesContext Cancellation, Timeout & Deadline

Context Cancellation, Timeout & Deadline

🧠 context (āĻ•āύāĻŸā§‡āĻ•ā§āϏāϟ) -> āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāύ⧋

context āĻšāϞ⧋ āĻāĻ•āϟāĻŋ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āϝāĻž āĻāĻ•āϟāĻŋ goroutine-āϕ⧇ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāχ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞāϗ⧁āϞ⧋ āĻšāϤ⧇ āĻĒāĻžāϰ⧇:

  • āĻ•ā§āϝāĻžāύāϏ⧇āϞ⧇āĻļāύ (Cancellation): “āϤ⧋āĻŽāĻžāϰ āĻ•āĻžāϜ āĻāĻ–āύ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧋āĨ¤â€
  • āϟāĻžāχāĻŽāφāωāϟ (Timeout): “āϤ⧋āĻŽāĻžāϰ āĻ•āĻžāϜ āϝāĻĻāĻŋ ā§Ģ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŽāĻ§ā§āϝ⧇ āĻļ⧇āώ āύāĻž āĻšā§Ÿ, āϤāĻŦ⧇ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇ āĻĻāĻŋāĻ“āĨ¤â€
  • āĻĄā§‡āĻĄāϞāĻžāχāύ (Deadline): “āϤ⧋āĻŽāĻžāϰ āĻ•āĻžāϜ āϰāĻžāϤ ā§§ā§§:ā§Ģ⧝ āĻŽāĻŋāύāĻŋāĻŸā§‡āϰ āĻŽāĻ§ā§āϝ⧇ āĻļ⧇āώ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇, āύāĻž āĻšāϞ⧇ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇ āĻĻāĻŋāĻ“āĨ¤â€

Context-āĻāϰ āĻĒā§āϰāϧāĻžāύ āĻ•āĻžāϜ āĻšāϞ⧋ goroutine-āĻĻ⧇āϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āĻžāĻœā§‡āϰ “āϞāĻžāχāĻĢāϏāĻžāχāϕ⧇āĻ˛â€ āĻŦāĻž āĻœā§€āĻŦāύāĻ•āĻžāϞ āĻŦ⧇āρāϧ⧇ āĻĻ⧇āĻ“ā§ŸāĻžāĨ¤


💧 āϏāĻŽāĻ¸ā§āϝāĻž: Goroutine Leak

Context āĻŦā§āϝāĻŦāĻšāĻžāϰ⧇āϰ āĻĒā§āϰāϧāĻžāύ āĻ•āĻžāϰāĻŖ āĻšāϞ⧋ Goroutine Leak (āĻ—ā§‹āϰ⧁āϟāĻŋāύ āϞāĻŋāĻ•) āĻĒā§āϰāϤāĻŋāϰ⧋āϧ āĻ•āϰāĻžāĨ¤

āĻāĻ•āϟāĻŋ “āϞāĻŋāĻ•â€ āϤāĻ–āύ āϘāĻŸā§‡ āϝāĻ–āύ āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ goroutine āϚāĻžāϞ⧁ āĻ•āϰ⧇āύ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϏ⧇āϟāĻŋ āĻļ⧇āώ āĻ•āϰāĻžāϰ āĻ•āĻĨāĻž āϭ⧁āϞ⧇ āϝāĻžāύ (āĻŦāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āύāĻž)āĨ¤ goroutine-āϟāĻŋ āĻŦā§āϝāĻžāĻ•āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄā§‡ āϚāϞāϤ⧇āχ āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻ“ CPU āĻ…āĻĒāϚ⧟ āĻ•āϰ⧇āĨ¤

āωāĻĻāĻžāĻšāϰāĻŖ: āϧāϰ⧁āύ āĻāĻ•āϟāĻŋ āĻ“ā§Ÿā§‡āĻŦ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇ āĻāĻ•āϜāύ āχāωāϜāĻžāϰ āĻāĻ•āϟāĻŋ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻĒāĻžāĻ āĻžāϞ⧋āĨ¤ āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ goroutine āϚāĻžāϞ⧁ āĻ•āϰāϞ⧇āύ āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻĨ⧇āϕ⧇ āϤāĻĨā§āϝ āφāύāĻžāϰ āϜāĻ¨ā§āϝāĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ āχāωāϜāĻžāϰ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟāϟāĻŋ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻ•āϰ⧇ āĻĻāĻŋāϞ⧋ (āĻŦā§āϰāĻžāωāϜāĻžāϰ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇ āĻĻāĻŋāϞ⧋)āĨ¤

  • Context āĻ›āĻžā§œāĻž: āφāĻĒāύāĻžāϰ āĻĄā§‡āϟāĻžāĻŦ⧇āϏ goroutine-āϟāĻŋ āϚāϞāϤ⧇āχ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤ āϏ⧇ āϜāĻžāύ⧇ āύāĻž āϝ⧇ āϤāĻžāϰ āĻ•āĻžāĻœā§‡āϰ āφāϰ āϕ⧋āύ⧋ āĻĻāϰāĻ•āĻžāϰ āύ⧇āχāĨ¤ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āϞāĻŋāĻ•āĨ¤
  • Context āϏāĻš: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšāĻ“ā§ŸāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ context āφāĻĒāύāĻžāϰ goroutine-āϕ⧇ āĻāĻ•āϟāĻŋ “āĻŦāĻ¨ā§āϧ āĻ•āĻ°ā§‹â€ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāĻŦ⧇āĨ¤ goroutine-āϟāĻŋ āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇ āĻĻ⧇āĻŦ⧇ āĻāĻŦāĻ‚ āϰāĻŋāϏ⧋āĻ°ā§āϏ āĻŽā§āĻ•ā§āϤ āĻ•āϰāĻŦ⧇āĨ¤

🎮 Context-āĻāϰ āϧāϰāĻŖ

Go-āϤ⧇ context āĻĒā§āϝāĻžāϕ⧇āϜāϟāĻŋ āĻāχ āϏ⧁āĻŦāĻŋāϧāĻžāϗ⧁āϞ⧋ āĻĻā§‡ā§ŸāĨ¤

🔹 1. context.Background()

  • 👉 āĻāϟāĻž āĻšāϞ⧋ root context
  • āϏāĻžāϧāĻžāϰāĻŖāϤ main āĻĢāĻžāĻ‚āĻļāύ āĻŦāĻž āĻāĻ•āϟāĻŋ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āĻŸā§‡āϰ āĻļ⧁āϰ⧁āϤ⧇ āĻāϟāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšā§ŸāĨ¤
  • āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻ–āĻžāϞāĻŋ context, āĻāϟāĻž āĻ•āĻ–āύ⧋ cancel āĻšā§Ÿ āύāĻž, āĻāϰ āϕ⧋āύ⧋ āϟāĻžāχāĻŽāφāωāϟ āύ⧇āχāĨ¤
ctx := context.Background()

📘 āĻāϰ āĻ“āĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇āχ WithCancel, WithTimeout āĻŦāĻž WithDeadline context āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšā§ŸāĨ¤


🔹 2. context.WithCancel(parentContext)

āĻāϟāĻŋ āĻāĻ•āϟāĻŋ parentContext (āϝ⧇āĻŽāύ Background()) āĻ¨ā§‡ā§Ÿ āĻāĻŦāĻ‚ āĻĻ⧁āϟāĻŋ āϜāĻŋāύāĻŋāϏ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇:

  1. āĻāĻ•āϟāĻŋ āύāϤ⧁āύ child context (ctx)āĨ¤
  2. āĻāĻ•āϟāĻŋ cancel āĻĢāĻžāĻ‚āĻļāύ (cancel)āĨ¤

āφāĻĒāύāĻŋ āϝāĻ–āύāχ cancel() āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āĻ•āϞ āĻ•āϰāĻŦ⧇āύ, āϤāĻ–āύ āϏ⧇āχ context āĻāĻŦāĻ‚ āϤāĻžāϰ āϏāĻŦ child context cancel āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

ctx, cancel := context.WithCancel(context.Background()) // `ctx` → āĻŽā§‚āϞ context object // `cancel` → āĻāχ function āĻ•āϞ āĻ•āϰāϞ⧇ context “cancel” āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤ // āĻāĻ–āĻžāύ⧇ āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ goroutine āϚāĻžāϞ⧁ āĻ•āϰāĻ›āĻŋ āϝāĻž ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻĒāϰ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻŦā§āϞāĻ• āĻšā§Ÿā§‡ āĻĨāĻžāĻ•āĻŦ⧇ go func() { <-time.After(3 * time.Second) // ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻĒāϰ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻŦā§āϞāĻ• āĻšā§Ÿā§‡ āĻĨāĻžāϕ⧋, āϤāĻžāϰāĻĒāϰ āĻāĻ—āĻŋā§Ÿā§‡ āϝāĻžāĻ“ cancel() // cancel after 3 seconds }() <-ctx.Done() fmt.Println("Context canceled:", ctx.Err())

🧩 Output:

Context canceled: context canceled
āĻ…āĻ‚āĻļāĻ•āĻžāϜ
time.After()āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ āĻĒāϰ⧇ signal āĻĒāĻžāĻ āĻžā§Ÿ
cancel()context cancel āĻ•āϰ⧇, Done() āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇
ctx.Done()cancellation signal āĻļā§‹āύ⧇
ctx.Err()āϕ⧇āύ cancel āĻšāϞ⧋ (Canceled / Timeout) āĻŦāϞ⧇

🔹 3. context.WithTimeout(parentContext, duration)

👉 āĻāχāϟāĻž āĻšāϞ⧋ “auto-cancel” āĻ•āϰāĻž context — āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ āĻĒāϰ⧇ āύāĻŋāĻœā§‡ āĻĨ⧇āϕ⧇āχ (automatically) cancel āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() // āĻāϟāĻž main() āĻĢāĻžāĻ‚āĻļāύ return āĻ•āϰāĻžāϰ āĻ āĻŋāĻ• āφāϗ⧇ āϰāĻžāύ āĻšāĻŦ⧇āĨ¤ select { case <-time.After(5 * time.Second): fmt.Println("Work finished") case <-ctx.Done(): fmt.Println("Timeout:", ctx.Err()) }

🧩 Output:

Timeout: context deadline exceeded

🧠 āĻŽāĻžāύ⧇ ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŽāĻ§ā§āϝ⧇ āĻ•āĻžāϜ āύāĻž āĻšāϞ⧇ context āύāĻŋāĻœā§‡āχ cancel āĻ•āϰ⧇ āĻĻā§‡ā§ŸāĨ¤

🔹 4. context.WithDeadline(parentContext, time)

👉 WithTimeout āĻāϰ āĻŽāϤ⧋āχ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ (clock time) āĻĒāĻ°ā§āϝāĻ¨ā§āϤ wait āĻ•āϰ⧇āĨ¤

deadline := time.Now().Add(2 * time.Second) ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel()

🔹 5. ctx.Done()

👉 ctx.Done() āĻšāϞ⧋ āĻāĻ•āϟāĻž channel āϝāĻž close āĻšā§Ÿā§‡ āϝāĻžā§Ÿ āϝāĻ–āύ context cancel āĻšā§ŸāĨ¤

select { case <-ctx.Done(): fmt.Println("🛑 Stopped:", ctx.Err()) }

🧠 āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ goroutine āĻŦ⧁āĻāϤ⧇ āĻĒāĻžāϰ⧇ — “āφāĻŽāĻžāϰ āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤â€


📡 Context āϝ⧇āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇

Context-āĻāϰ āĻĻ⧁āϟāĻŋ āĻŽā§‚āϞ āĻ…āĻ‚āĻļ: āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāύ⧋ āĻāĻŦāĻ‚ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰāĻžāĨ¤

ā§§. āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāύ⧋ (āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻ•āϰāĻž): WithCancel-āĻāϰ cancel() āĻĢāĻžāĻ‚āĻļāύ āĻ•āϞ āĻ•āϰāĻž āĻšāϞ⧇, āĻ…āĻĨāĻŦāĻž WithTimeout-āĻāϰ āϏāĻŽā§Ÿ āĻļ⧇āώ āĻšāϞ⧇ context āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

⧍. āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰāĻž (ctx.Done()): āĻĒā§āϰāϤāĻŋāϟāĻŋ context-āĻāϰ āĻāĻ•āϟāĻŋ .Done() āĻŽā§‡āĻĨāĻĄ āφāϛ⧇, āϝāĻž āĻāĻ•āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇āĨ¤

  • Context āϝāϤāĻ•ā§āώāĻŖ āĻ…ā§āϝāĻžāĻ•ā§āϟāĻŋāĻ­ āĻĨāĻžāϕ⧇, āĻāχ āĻšā§āϝāĻžāύ⧇āϞāϟāĻŋ āĻŦā§āϞāĻ• āĻĨāĻžāϕ⧇āĨ¤
  • Context āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšāĻ“ā§ŸāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āĻāχ āĻšā§āϝāĻžāύ⧇āϞāϟāĻŋ āĻŦāĻ¨ā§āϧ (closed) āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

āφāĻŽāϰāĻž āϜāĻžāύāĻŋ, āĻāĻ•āϟāĻŋ āĻŦāĻ¨ā§āϧ āĻšā§āϝāĻžāύ⧇āϞ āĻĨ⧇āϕ⧇ āϰāĻŋāĻĄ āĻ•āϰāĻž āĻšāϞ⧇ āϤāĻž āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇āĨ¤ āφāĻŽāϰāĻž āĻāχ āϏ⧁āĻŦāĻŋāϧāĻžāϟāĻŋ select-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŋ:

select { case <-ctx.Done(): // Context āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšā§Ÿā§‡ āϗ⧇āϛ⧇ (āϟāĻžāχāĻŽāφāωāϟ āĻŦāĻž āĻŽā§āϝāĻžāύ⧁⧟āĻžāϞ)! // āĻāĻ–āĻžāύ⧇ āϏāĻŦ āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇, āϰāĻŋāϏ⧋āĻ°ā§āϏ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤ fmt.Println("āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻ›āĻŋ...") return // goroutine āĻĨ⧇āϕ⧇ āĻŦ⧇āϰ āĻšā§Ÿā§‡ āϝāĻžāχ default: // Context āĻāĻ–āύ⧋ āĻ…ā§āϝāĻžāĻ•ā§āϟāĻŋāĻ­ āφāϛ⧇, āĻ•āĻžāϜ āϚāĻžāϞāĻŋā§Ÿā§‡ āϝāĻžāχ fmt.Println("āĻ•āĻžāϜ āϚāϞāϛ⧇...") }

🔗 Context Propagation (āĻĒā§āϰ⧋āĻĒāĻžāϗ⧇āĻļāύ)

āĻāϟāĻŋ context-āĻāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāĨ¤

āϝāĻ–āύ āĻāĻ•āϟāĻŋ Parent Context āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšā§Ÿ, āϤāĻ–āύ āϤāĻžāϰ āĻĨ⧇āϕ⧇ āϤ⧈āϰāĻŋ āϏāĻŦ Child Context-āĻ“ āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

āĻ āĻ•āĻžāϰāϪ⧇āχ context āϏāĻŦāϏāĻŽā§Ÿ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻĒāĻžāϏ āĻ•āϰāĻž āĻšā§Ÿ: func myWorker(ctx context.Context, otherArg string)āĨ¤

  • main āĻāĻ•āϟāĻŋ ctx āϤ⧈āϰāĻŋ āĻ•āϰ⧇āĨ¤
  • main āĻ•āϞ āĻ•āϰ⧇ funcA(ctx)āĨ¤
  • funcA āĻ•āϞ āĻ•āϰ⧇ funcB(ctx)āĨ¤
  • funcB āĻ•āϞ āĻ•āϰ⧇ funcC(ctx)āĨ¤

āϝāĻĻāĻŋ main āĻĢāĻžāĻ‚āĻļāύ ctx-āϕ⧇ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻ•āϰ⧇ (āϝ⧇āĻŽāύ, āχāωāϜāĻžāϰ⧇āϰ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āϟāĻžāχāĻŽāφāωāϟ āĻšāϞ⧋), āϏ⧇āχ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞāϟāĻŋ funcA, funcB, āĻāĻŦāĻ‚ funcC-āϤ⧇ āĻĨāĻžāĻ•āĻž āϏāĻŦ goroutine-āĻāϰ āĻ•āĻžāϛ⧇ āĻĒ⧌āρāϛ⧇ āϝāĻžāĻŦ⧇ (<-ctx.Done())āĨ¤ āϏāĻŦāĻžāχ āĻāĻ•āϝ⧋āϗ⧇ āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰ⧇ āĻĻ⧇āĻŦ⧇āĨ¤


đŸ’ģ āφāϜāϕ⧇āϰ āĻ…āύ⧁āĻļā§€āϞāύ (Exercises)

āφāϏ⧁āύ, āωāĻĒāϰ⧇āϰ āϏāĻŦ āϧāĻžāϰāĻŖāĻž āϕ⧋āĻĄ āĻ•āϰ⧇ āĻĻ⧇āĻ–āĻŋāĨ¤

āĻ…āύ⧁āĻļā§€āϞāύ ā§§ āĻāĻŦāĻ‚ ⧍: WithTimeout (āĻŽā§āϝāĻžāύ⧁⧟āĻžāϞ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻāĻŦāĻ‚ āϟāĻžāχāĻŽāφāωāϟ)

āĻāχ āĻ…āύ⧁āĻļā§€āϞāύ⧇ āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ worker āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ āϝāĻž āĻāĻ•āϟāĻŋ context āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤ āφāĻŽāϰāĻž āĻĻ⧇āĻ–āĻŦ ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻĒāϰ āĻāϟāĻŋ āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇ āĻŦāĻ¨ā§āϧ āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤

package main import ( "context" "fmt" "time" ) // worker āĻšāϞ⧋ āĻāĻ•āϟāĻŋ goroutine āϝāĻž context āĻļ⧇āώ āύāĻž āĻšāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ•āĻžāϜ āĻ•āϰ⧇ func worker(ctx context.Context, name string) { fmt.Printf("👷 %s: āĻ•āĻžāϜ āĻļ⧁āϰ⧁...\n", name) for { select { case <-ctx.Done(): // āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒā§‡ā§Ÿā§‡āĻ›āĻŋ! fmt.Printf("🛑 %s: āĻ•ā§āϝāĻžāύāϏ⧇āϞ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒ⧇āϞāĻžāĻŽ, āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻ›āĻŋāĨ¤\n", name) return // goroutine āĻĨ⧇āϕ⧇ āĻĒā§āϰāĻ¸ā§āĻĨāĻžāύ default: // Context āĻ āĻŋāĻ• āĻĨāĻžāĻ•āϞ⧇ āĻ•āĻžāϜ āϚāĻžāϞāĻŋā§Ÿā§‡ āϝāĻžāχ fmt.Printf("âš™ī¸ %s: āĻ•āĻžāϜ āĻ•āϰāĻ›āĻŋ...\n", name) time.Sleep(1 * time.Second) // āĻ•āĻžāĻœā§‡āϰ āϏāĻŋāĻŽā§āϞ⧇āĻļāύ } } } func main() { // ā§§. āĻāĻ•āϟāĻŋ parent context āϤ⧈āϰāĻŋ āĻ•āϰāĻŋ parentCtx := context.Background() // ⧍. ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻāĻ•āϟāĻŋ āϟāĻžāχāĻŽāφāωāϟ āϏāĻš child context āϤ⧈āϰāĻŋ āĻ•āϰāĻŋ ctx, cancel := context.WithTimeout(parentCtx, 3*time.Second) // ā§Š. (āϖ⧁āĻŦāχ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ) āĻ•āĻžāϜ āĻļ⧇āώ⧇ cancel() āĻ•āϞ āĻ•āϰāĻž // āĻāϟāĻŋ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧇ āϝ⧇ context-āĻāϰ āϏāĻžāĻĨ⧇ āϝ⧁āĻ•ā§āϤ āϏāĻŦ āϰāĻŋāϏ⧋āĻ°ā§āϏ āĻŽā§āĻ•ā§āϤ āĻšāĻŦ⧇āĨ¤ // āϝāĻĻāĻŋāĻ“ āϟāĻžāχāĻŽāφāωāϟ āĻšāϞ⧇ āĻāϟāĻŋ āύāĻŋāĻœā§‡ āĻĨ⧇āϕ⧇āχ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšāĻŦ⧇, // āĻ•āĻŋāĻ¨ā§āϤ⧁ āϝāĻĻāĻŋ worker āφāϗ⧇ āĻ•āĻžāϜ āĻļ⧇āώ āĻ•āϰ⧇ āĻĢ⧇āϞ⧇, āϤāĻŦ⧇ defer cancel() āϰāĻŋāϏ⧋āĻ°ā§āϏ āϞāĻŋāĻ• āϠ⧇āĻ•āĻžā§ŸāĨ¤ defer cancel() fmt.Println("🚀 main: āĻ“ā§ŸāĻžāĻ°ā§āĻ•āĻžāϰ āϚāĻžāϞ⧁ āĻ•āϰāĻ›āĻŋ (ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϟāĻžāχāĻŽāφāωāϟ)...") go worker(ctx, "Worker-1") // main goroutine-āϕ⧇ ā§Ģ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϚāĻžāϞ⧁ āϰāĻžāĻ–āĻŋ āϝāĻžāϤ⧇ worker-āĻāϰ āĻĒā§āϰāĻ¸ā§āĻĨāĻžāύ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāϰāĻŋ time.Sleep(5 * time.Second) fmt.Println("👋 main: āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻļ⧇āώāĨ¤") }

āφāωāϟāĻĒ⧁āϟ:

🚀 main: āĻ“ā§ŸāĻžāĻ°ā§āĻ•āĻžāϰ āϚāĻžāϞ⧁ āĻ•āϰāĻ›āĻŋ (ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϟāĻžāχāĻŽāφāωāϟ)... 👷 Worker-1: āĻ•āĻžāϜ āĻļ⧁āϰ⧁... âš™ī¸ Worker-1: āĻ•āĻžāϜ āĻ•āϰāĻ›āĻŋ... âš™ī¸ Worker-1: āĻ•āĻžāϜ āĻ•āϰāĻ›āĻŋ... âš™ī¸ Worker-1: āĻ•āĻžāϜ āĻ•āϰāĻ›āĻŋ... 🛑 Worker-1: āĻ•ā§āϝāĻžāύāϏ⧇āϞ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒ⧇āϞāĻžāĻŽ, āĻ•āĻžāϜ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻ›āĻŋāĨ¤ 👋 main: āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻļ⧇āώāĨ¤

āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ: Worker-1 āĻ āĻŋāĻ• ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻ•āĻžāϜ āĻ•āϰāĻžāϰ āĻĒāϰ <-ctx.Done() āĻĨ⧇āϕ⧇ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžā§Ÿ āĻāĻŦāĻ‚ āĻŦāĻ¨ā§āϧ āĻšā§Ÿā§‡ āϝāĻžā§ŸāĨ¤


āĻ…āύ⧁āĻļā§€āϞāύ ā§Š, ā§Ē āĻāĻŦāĻ‚ ā§Ģ: Context āĻšā§‡āχāύ āĻāĻŦāĻ‚ āĻ“ā§ŸāĻžāĻ°ā§āĻ•āĻžāϰ āĻ•ā§āϝāĻžāύāϏ⧇āϞ⧇āĻļāύ

āĻāĻ–āĻžāύ⧇ āφāĻŽāϰāĻž āĻĻ⧇āĻ–āĻŦ context āϕ⧀āĻ­āĻžāĻŦ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻŽāĻ§ā§āϝ⧇ (āĻšā§‡āχāύ) āĻĒāĻžāϏ āĻ•āϰāĻž āĻšā§Ÿ āĻāĻŦāĻ‚ āĻ•ā§āϝāĻžāύāϏ⧇āϞ⧇āĻļāύ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤

package main import ( "context" "fmt" "time" ) // step3: āφāϏāϞ āĻ•āĻžāϜ āĻāĻ–āĻžāύ⧇ āĻšā§Ÿ (āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āϏāĻŋāĻŽā§āϞ⧇āĻļāύ) func step3(ctx context.Context) { fmt.Println(" [Step 3]: āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āĻļ⧁āϰ⧁... (⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϞāĻžāĻ—āĻŦ⧇)") select { case <-time.After(2 * time.Second): // āĻ•āĻžāϜ āϏāĻŽā§āĻĒāĻ¨ā§āύ fmt.Println(" [Step 3]: āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āϏāĻĢāϞāĨ¤") case <-ctx.Done(): // āĻ•āĻžāϜ āĻļ⧇āώ āĻšāĻ“ā§ŸāĻžāϰ āφāϗ⧇āχ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻāϞ⧋ fmt.Println(" [Step 3]: 🛑 āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āĻ•ā§āϝāĻžāύāϏ⧇āϞāĻĄ!") } } // step2: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏ āĻ•āϰ⧇ func step2(ctx context.Context) { fmt.Println(" [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧁āϰ⧁...") // āĻ•āĻžāϜ āĻ•āϰāĻžāϰ āφāϗ⧇ āĻšā§‡āĻ• āĻ•āϰāĻž (Early exit) if ctx.Err() != nil { fmt.Println(" [Step 2]: 🛑 āĻļ⧁āϰ⧁āϤ⧇āχ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻ›āĻŋāϞ⧋, āĻ•āĻžāϜ āĻļ⧁āϰ⧁āχ āĻ•āϰāϞāĻžāĻŽ āύāĻžāĨ¤") return } step3(ctx) // context āύāĻŋāĻšā§‡ āĻĒāĻžāϏ āĻ•āϰāĻž fmt.Println(" [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧇āώāĨ¤") } // step1: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ āĻ•āϰ⧇ func step1(ctx context.Context) { fmt.Println("[Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧁āϰ⧁...") step2(ctx) // context āύāĻŋāĻšā§‡ āĻĒāĻžāϏ āĻ•āϰāĻž fmt.Println("[Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧇āώāĨ¤") } func main() { // === āϏāĻŋāύāĻžāϰāĻŋāĻ“ ā§§: āϏāĻĢāϞ (āϟāĻžāχāĻŽāφāωāĻŸā§‡āϰ āφāϗ⧇āχ āĻ•āĻžāϜ āĻļ⧇āώ) === fmt.Println("--- āϏāĻŋāύāĻžāϰāĻŋāĻ“ ā§§: āϏāĻĢāϞ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ (āϟāĻžāχāĻŽāφāωāϟ ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) ---") ctxSuccess, cancelSuccess := context.WithTimeout(context.Background(), 3*time.Second) defer cancelSuccess() step1(ctxSuccess) fmt.Println("\n--- āϏāĻŋāύāĻžāϰāĻŋāĻ“ ⧍: āĻ•ā§āϝāĻžāύāϏ⧇āϞāĻĄ (āϟāĻžāχāĻŽāφāωāϟ ā§§ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) ---") // === āϏāĻŋāύāĻžāϰāĻŋāĻ“ ⧍: āĻ•ā§āϝāĻžāύāϏ⧇āϞāĻĄ (āϟāĻžāχāĻŽāφāωāĻŸā§‡āϰ āφāϗ⧇āχ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ) === ctxTimeout, cancelTimeout := context.WithTimeout(context.Background(), 1*time.Second) defer cancelTimeout() step1(ctxTimeout) // āĻ•ā§āϝāĻžāύāϏ⧇āϞ⧇āĻļāύ⧇āϰ āĻĒā§āϰāĻ­āĻžāĻŦ āĻĻ⧇āĻ–āĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟ⧁ āĻ…āĻĒ⧇āĻ•ā§āώāĻž time.Sleep(2 * time.Second) fmt.Println("--- āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻļ⧇āώ ---") }

āφāωāϟāĻĒ⧁āϟ:

--- āϏāĻŋāύāĻžāϰāĻŋāĻ“ ā§§: āϏāĻĢāϞ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ (āϟāĻžāχāĻŽāφāωāϟ ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) --- [Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧁āϰ⧁... [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧁āϰ⧁... [Step 3]: āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āĻļ⧁āϰ⧁... (⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϞāĻžāĻ—āĻŦ⧇) [Step 3]: āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āϏāĻĢāϞāĨ¤ [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧇āώāĨ¤ [Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧇āώāĨ¤ --- āϏāĻŋāύāĻžāϰāĻŋāĻ“ ⧍: āĻ•ā§āϝāĻžāύāϏ⧇āϞāĻĄ (āϟāĻžāχāĻŽāφāωāϟ ā§§ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) --- [Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧁āϰ⧁... [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧁āϰ⧁... [Step 3]: āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āĻļ⧁āϰ⧁... (⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϞāĻžāĻ—āĻŦ⧇) [Step 3]: 🛑 āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻ•ā§‹ā§Ÿā§‡āϰāĻŋ āĻ•ā§āϝāĻžāύāϏ⧇āϞāĻĄ! [Step 2]: āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ āĻļ⧇āώāĨ¤ [Step 1]: āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞāĻŋāĻ‚ āĻļ⧇āώāĨ¤ --- āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻļ⧇āώ ---

āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ:

  • āϏāĻŋāύāĻžāϰāĻŋāĻ“ ā§§: ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āϟāĻžāχāĻŽāφāωāϟ āĻ›āĻŋāϞ⧋, āĻ•āĻŋāĻ¨ā§āϤ⧁ step3-āĻāϰ āĻ•āĻžāϜ ⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡ āĻļ⧇āώ āĻšā§Ÿā§‡ āϗ⧇āϛ⧇āĨ¤ āϤāĻžāχ <-ctx.Done() āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āφāϏāĻžāϰ āφāϗ⧇āχ <-time.After() āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞāϟāĻŋ āϜāĻŋāϤ⧇āϛ⧇āĨ¤
  • āϏāĻŋāύāĻžāϰāĻŋāĻ“ ⧍: ā§§ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āϟāĻžāχāĻŽāφāωāϟ āĻ›āĻŋāϞ⧋, āĻ•āĻŋāĻ¨ā§āϤ⧁ step3-āĻāϰ āĻ•āĻžāϜ ⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āϞāĻžāĻ—āĻžāϰ āĻ•āĻĨāĻžāĨ¤ select āĻ¸ā§āĻŸā§‡āϟāĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻĻ⧇āĻ–āϞ⧋ āϝ⧇ <-ctx.Done() (ā§§ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞāϟāĻŋ <-time.After() (⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ) āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ⧇āϰ āφāϗ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻšā§Ÿā§‡āϛ⧇āĨ¤ āϤāĻžāχ āĻāϟāĻŋ āĻ•ā§āϝāĻžāύāϏ⧇āϞ⧇āĻļāύ āĻĒāĻžāĻĨāϟāĻŋ āĻŦ⧇āϛ⧇ āύāĻŋāϞ⧋āĨ¤

đŸšĢ āϏāĻžāϧāĻžāϰāĻŖ āϭ⧁āϞ āĻāĻŦāĻ‚ ✅ āϏāĻ āĻŋāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ

Context āϖ⧁āĻŦ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāϟāĻŋ āϭ⧁āϞāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāĻ“ āϖ⧁āĻŦ āϏāĻšāϜāĨ¤

āϏāĻžāϧāĻžāϰāĻŖ āϭ⧁āϞ (Avoid)✅ āϏāĻ āĻŋāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ (Do)
context āĻāĻ•āϟāĻŋ struct-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻ¸ā§āĻŸā§‹āϰ āĻ•āϰāĻžāĨ¤context-āϕ⧇ āϏāĻŦāϏāĻŽā§Ÿ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻĒāĻžāϏ āĻ•āϰ⧁āύ: func(ctx context.Context, ...)āĨ¤
context.Background() āϏāĻŦ āϜāĻžā§ŸāĻ—āĻžā§Ÿ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāĨ¤context.Background() āĻļ⧁āϧ⧁ main āĻŦāĻž āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āĻŸā§‡āϰ āĻļ⧁āϰ⧁āϤ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤ āĻŦāĻžāĻ•āĻŋ āϏāĻŦ āϜāĻžā§ŸāĻ—āĻžā§Ÿ āĻĒāĻžāϏ āĻ•āϰāĻž ctx āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤
cancel() āĻĢāĻžāĻ‚āĻļāύ āĻ•āϞ āύāĻž āĻ•āϰāĻžāĨ¤defer cancel() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤ context.With... āĻ•āϞ āĻ•āϰāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇āχ defer cancel() āϞāĻŋāϖ⧇ āĻĢ⧇āϞ⧁āύāĨ¤ āĻāϟāĻŋ āϰāĻŋāϏ⧋āĻ°ā§āϏ āϞāĻŋāĻ• āϠ⧇āĻ•āĻžā§ŸāĨ¤
context.TODO() āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āϕ⧋āĻĄā§‡ āϰ⧇āϖ⧇ āĻĻ⧇āĻ“ā§ŸāĻžāĨ¤TODO() āĻļ⧁āϧ⧁ āϤāĻ–āύāχ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ āϝāĻ–āύ āφāĻĒāύāĻŋ āύāĻŋāĻļā§āϚāĻŋāϤ āύāύ āϕ⧋āύ context āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ (āĻāĻŦāĻ‚ āĻĒāϰ⧇ āϤāĻž āĻ āĻŋāĻ• āĻ•āϰāĻŦ⧇āύ)āĨ¤
nil context āĻĒāĻžāϏ āĻ•āϰāĻžāĨ¤nil āĻĒāĻžāϏ āύāĻž āĻ•āϰ⧇, āϝāĻĻāĻŋ āϕ⧋āύ⧋ context āύāĻž āĻĨāĻžāϕ⧇ āϤāĻŦ⧇ context.Background() āĻĒāĻžāϏ āĻ•āϰ⧁āύāĨ¤
context-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻĄā§‡āϟāĻž āĻĒāĻžāϏ āĻ•āϰāĻž (WithValue)āĨ¤WithValue āĻā§œāĻŋā§Ÿā§‡ āϚāϞ⧁āύ, āϝāĻĻāĻŋ āύāĻž āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ-āĻ¸ā§āϕ⧋āĻĒāĻĄ āĻĄā§‡āϟāĻž (āϝ⧇āĻŽāύ trace ID, user ID) āĻĒāĻžāϏ āĻ•āϰāĻžāϰ āĻĻāϰāĻ•āĻžāϰ āĻšā§ŸāĨ¤ āĻāϟāĻŋ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞāĻŋāĻ‚ā§Ÿā§‡āϰ āϜāĻ¨ā§āϝ āύ⧟āĨ¤

🔹 4. context.WithDeadline(parent, timePoint)

👉 WithTimeout āĻāϰ āĻŽāϤ⧋āχ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ (clock time) āĻĒāĻ°ā§āϝāĻ¨ā§āϤ wait āĻ•āϰ⧇āĨ¤

deadline := time.Now().Add(2 * time.Second) ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel()

🧩 Context Propagation āϕ⧀āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇?

Context āĻšāϞ⧋ parent → child chain.

Background() └── WithCancel() └── WithTimeout() └── WithDeadline()

āϝāĻĻāĻŋ parent cancel āĻšā§Ÿ → āϏāĻŦ child context āĻ“ cancel āĻšā§ŸāĨ¤ āĻāϟāĻžāχ āĻŦāϞ⧇ propagationāĨ¤


âš™ī¸ āϕ⧇āύ Context āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āϰāĻĨāĻŽ argument āĻšā§Ÿ?

👉 āĻ•āĻžāϰāĻŖ Go design principle āĻ…āύ⧁āϝāĻžā§Ÿā§€ context āĻšāϞ⧋ request-scoped metadataāĨ¤ āĻāϟāĻž function āĻāϰ lifecycle āύāĻŋ⧟āĻ¨ā§āĻ¤ā§āϰāĻŖ āĻ•āϰ⧇āĨ¤

✅ Best Practice:

func fetchData(ctx context.Context, url string) error

❌ Wrong:

func fetchData(url string, ctx context.Context)

🧠 āĻ•āĻžāϰāĻŖ: Context āϏāĻ°ā§āĻŦāĻĻāĻž āωāĻĒāϰ⧇āϰ āĻĻāĻŋāĻ• āĻĨ⧇āϕ⧇ āύāĻŋāĻšā§‡āϰ āĻĻāĻŋāϕ⧇ propagate āĻšā§ŸāĨ¤


💡 Context āĻ•āĻŋāĻ­āĻžāĻŦ⧇ Goroutine Leak āφāϟāĻ•āĻžā§Ÿ

Goroutine leak āĻšā§Ÿ āϝāĻ–āύ goroutine cancel signal āύāĻž āĻĒā§‡ā§Ÿā§‡ āϚāĻŋāϰāĻĻāĻŋāύ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇āĨ¤

❌ āωāĻĻāĻžāĻšāϰāĻŖ:

func worker(ch <-chan int) { for v := range ch { fmt.Println(v) } }

āϝāĻĻāĻŋ ch āĻ•āĻ–āύ⧋ close āύāĻž āĻšā§Ÿ → goroutine āϚāĻŋāϰāĻĻāĻŋāύ block āĻĨāĻžāĻ•āĻŦ⧇āĨ¤

✅ āϏāĻŽāĻžāϧāĻžāύ: Context āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻžāĨ¤

func worker(ctx context.Context, ch <-chan int) { for { select { case v := <-ch: fmt.Println(v) case <-ctx.Done(): fmt.Println("Worker stopped") return } } }

đŸ’ģ Exercises

🧩 1ī¸âƒŖ Goroutine that stops when context is canceled

package main import ( "context" "fmt" "time" ) func main() { ctx, cancel := context.WithCancel(context.Background()) go func() { for { select { case <-ctx.Done(): fmt.Println("🛑 Goroutine stopped") return default: fmt.Println("🏃 Running...") time.Sleep(500 * time.Millisecond) } } }() time.Sleep(2 * time.Second) cancel() // stop after 2 seconds time.Sleep(1 * time.Second) }

🧩 2ī¸âƒŖ WithTimeout — stop after 3 seconds

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() go func() { for { select { case <-ctx.Done(): fmt.Println("⏰ Timeout reached:", ctx.Err()) return default: fmt.Println("âš™ī¸ Working...") time.Sleep(500 * time.Millisecond) } } }() time.Sleep(4 * time.Second)

🧩 3ī¸âƒŖ Chain 3 Goroutines passing context downstream

func worker(ctx context.Context, name string) { for { select { case <-ctx.Done(): fmt.Println(name, "stopped") return default: fmt.Println(name, "working...") time.Sleep(700 * time.Millisecond) } } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() go worker(ctx, "🧱 Worker 1") go worker(ctx, "🔧 Worker 2") go worker(ctx, "âš™ī¸ Worker 3") <-ctx.Done() fmt.Println("All workers stopped:", ctx.Err()) }

🧩 4ī¸âƒŖ Cleanup with <-ctx.Done()

select { case <-ctx.Done(): fmt.Println("Cleaning up resources...") return }

🧩 5ī¸âƒŖ Worker respecting cancellation

func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Worker %d shutting down\n", id) return default: fmt.Printf("Worker %d doing work\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() for i := 1; i <= 3; i++ { go worker(ctx, i) } <-ctx.Done() fmt.Println("🛑 All workers canceled:", ctx.Err()) }

âš ī¸ Common Mistakes & Correct Usage

āϭ⧁āϞ āĻŦā§āϝāĻŦāĻšāĻžāϰ ❌āϏāĻ āĻŋāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ ✅
Context āύāĻž āĻĒāĻžāĻ āĻžāύ⧋āϏāĻŦ goroutine/fn-āĻ context āĻĒāĻžāĻ āĻžāĻ“
Context āĻļ⧇āώ⧇āĻ“ cancel() āύāĻž āĻ•āϰāĻžāϏāĻŦāϏāĻŽā§Ÿ defer cancel() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧋
cancel() āύāĻž āĻĄāĻžāĻ•āĻžresource leak āĻšāϤ⧇ āĻĒāĻžāϰ⧇
context child chain āύāĻž āĻŦāĻžāύāĻžāύ⧋parent → child propagation āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧋
context.TODO() āϭ⧁āϞāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ placeholder āĻšāĻŋāϏ⧇āĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧋
<-ctx.Done() ignore āĻ•āϰāĻžāϏāĻŦ worker āĻ respect āĻ•āϰāĻž āωāϚāĻŋāϤ

🧾 Summary (āĻŦāĻžāĻ‚āϞāĻžā§Ÿ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ)

āĻŦāĻŋāώ⧟āĻŦāĻ°ā§āĻŖāύāĻž
context.Background()root context
WithCancelmanual cancel
WithTimeoutāύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ āĻĒāϰ auto-cancel
WithDeadlineāύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ valid
ctx.Done()context cancel signal
ctx.Err()āϕ⧇āύ cancel āĻšāϞ⧋
Context chainparent cancel āĻšāϞ⧇ āϏāĻŦ child cancel
Leak preventiongoroutine cancel signal āĻĒ⧇āϞ⧇ safely stop āĻšā§Ÿ

āĻāĻ•āϜāύ āϏāĻŋāύāĻŋ⧟āϰāĻŋ āĻĄā§‡āϭ⧇āϞāĻĒāĻžāϰ āĻŦāĻž āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ Context āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āϝāĻž āϝāĻž āϜāĻžāύāĻž āĻ…āĻĒāϰāĻŋāĻšāĻžāĻ°ā§āϝ, āϤāĻžāϰ āϏāĻŦāĻ•āĻŋāϛ⧁ āĻāĻ–āĻžāύ⧇ āϗ⧁āĻ›āĻŋā§Ÿā§‡ āĻĻ⧇āĻ“ā§ŸāĻž āĻšāϞ⧋āĨ¤

🚀 Go Context: The Nervous System of Production Apps

Go-āϤ⧇ Context āϕ⧋āύ⧋ āϏāĻžāϧāĻžāϰāĻŖ āϭ⧇āϰāĻŋā§Ÿā§‡āĻŦāϞ āύ⧟; āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ⧇āϰ Nervous System āĻŦāĻž āĻ¸ā§āύāĻžā§Ÿā§āϤāĻ¨ā§āĻ¤ā§āϰāĨ¤ āĻāĻ•āϟāĻŋ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āϝāĻ–āύ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇ āĻĸā§‹āϕ⧇, āϤāĻ–āύ Context āϤāĻžāϰ āϏāĻžāĻĨ⧇ āĻĒ⧁āϰ⧋ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āĻĒā§āϰāĻŦāĻžāĻšāĻŋāϤ āĻšā§Ÿ āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āϧāĻžāϰāĻŖ āĻ•āϰ⧇ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟāϟāĻŋ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻŦ⧇ āύāĻžāĻ•āĻŋ āĻŽāĻžāϰāĻž āϝāĻžāĻŦ⧇ (Cancel āĻšāĻŦ⧇)āĨ¤

Production Philosophy: “Never start a goroutine without knowing how it will stop.” — Context āĻšāϞ⧋ āϏ⧇āχ āĻ¸ā§āϟāĻĒ āĻŦāĻžāϟāύāĨ¤


ā§§. Production Hierarchy (Context Tree)

āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ⧇ Context āϏāĻ°ā§āĻŦāĻĻāĻž āĻāĻ•āϟāĻŋ Tree āĻāϰ āĻŽāϤ⧋ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤

Background Context (Root) └─→ HTTP Request Context ├─→ Database Query Context ├─→ API Call Context └─→ Redis Cache Context
  • Root: context.Background() (āĻ…ā§āϝāĻžāĻĒ āϚāĻžāϞ⧁ āĻšāĻ“ā§ŸāĻžāϰ āϏāĻŽā§Ÿ)āĨ¤
  • Parent: āϝāĻ–āύ HTTP āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āφāϏ⧇ (http.Request).
  • Children: āϝāĻ–āύ āφāĻĒāύāĻŋ DB āĻ•ā§ā§Ÿā§‡āϰāĻŋ āĻŦāĻž āĻ…āĻ¨ā§āϝ API āĻ•āϞ āĻ•āϰ⧇āύ, āϤāĻ–āύ Parent āĻĨ⧇āϕ⧇ āύāϤ⧁āύ Context āϤ⧈āϰāĻŋ āĻšā§Ÿ (WithTimeout)āĨ¤

Rule: āϝāĻĻāĻŋ Parent āĻŽāĻžāϰāĻž āϝāĻžā§Ÿ (User cancel request), āϤāĻŦ⧇ āϤāĻžāϰ āϏāĻŦ Children (DB, API calls) āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻŦ⧇ āĻāĻŦāĻ‚ āĻŦāĻ¨ā§āϧ āĻšā§Ÿā§‡ āϝāĻžāĻŦ⧇āĨ¤ āĻāϟāĻŋ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āϰāĻŋāϏ⧋āĻ°ā§āϏ āĻŦāĻžāρāϚāĻžā§ŸāĨ¤


⧍. Context-āĻāϰ āĻĒā§āϰāĻ•āĻžāϰāϭ⧇āĻĻ (Production Use-Cases)

Context TypeāĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ? (Real World)
Background()āĻļ⧁āϧ⧁ main() āĻĢāĻžāĻ‚āĻļāύ āĻŦāĻž āĻ…ā§āϝāĻžāĻĒ āĻ¸ā§āϟāĻžāĻ°ā§āϟāφāĻĒ⧇āĨ¤
TODO()āϝāĻ–āύ āϕ⧋āĻĄ āϞāĻŋāĻ–āϛ⧇āύ āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāĻ–āύ⧋ āϜāĻžāύ⧇āύ āύāĻž āϕ⧋āύ Context āĻĻ⧇āĻŦ⧇āύ (Refactoring-āĻāϰ āϏāĻŽā§Ÿ)āĨ¤
WithCancelāϝāĻ–āύ āĻŽā§āϝāĻžāύ⧁⧟āĻžāϞāĻŋ āϕ⧋āύ⧋ āĻĒā§āϰāϏ⧇āϏ āĻŦāĻ¨ā§āϧ āĻ•āϰāϤ⧇ āϚāĻžāύ (āϝ⧇āĻŽāύ: Graceful Shutdown)āĨ¤
WithTimeoutāϏāĻŦāĻšā§‡ā§Ÿā§‡ āĻŦ⧇āĻļāĻŋ āĻŦā§āϝāĻŦāĻšā§ƒāϤāĨ¤ DB Query, External API Call āĻŦāĻž āϝ⧇āϕ⧋āύ⧋ I/O āĻ…āĻĒāĻžāϰ⧇āĻļāύ⧇āĨ¤
WithDeadlineāϝāĻ–āύ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϘ⧜āĻŋāϰ āϏāĻŽā§Ÿ (āϝ⧇āĻŽāύ: “āϰāĻžāϤ ⧧⧍āϟāĻžāϰ āφāĻ—ā§‡â€) āĻ•āĻžāϜ āĻļ⧇āώ āĻšāϤ⧇āχ āĻšāĻŦ⧇āĨ¤
WithValueāĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ Request-Scoped Data (Trace ID, Auth Token) āĻĒāĻžāϏ āĻ•āϰāϤ⧇āĨ¤ āĻ•āĻ–āύ⧋ āĻĢāĻžāĻ‚āĻļāύ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āĻĒāĻžāϏ āĻ•āϰāĻŦ⧇āύ āύāĻžāĨ¤

ā§Š. Production Pattern: HTTP Request Handling

āĻāĻ•āϟāĻŋ āφāĻĻāĻ°ā§āĻļ āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇ āĻ•ā§āϞāĻžāϝāĻŧ⧇āĻ¨ā§āϟ āϝāĻĻāĻŋ āϏāĻ‚āϝ⧋āĻ— āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ āĻ•āϰ⧇, āϤāĻŦ⧇ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āĻ•āĻžāϜāĻ“ āĻŦāĻ¨ā§āϧ āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤāĨ¤

func handler(w http.ResponseWriter, r *http.Request) { // ā§§. http.Request āύāĻŋāĻœā§‡āχ āĻāĻ•āϟāĻŋ context āύāĻŋāϝāĻŧ⧇ āφāϏ⧇ ctx := r.Context() fmt.Println("Processing request...") select { case <-time.After(5 * time.Second): // āĻ­āĻžāϰ⧀ āĻ•āĻžāϜ āϏāĻŋāĻŽā§āϞ⧇āĻļāύ w.Write([]byte("Request Processed")) case <-ctx.Done(): // ⧍. āϝāĻĻāĻŋ āχāωāϜāĻžāϰ āĻŦā§āϰāĻžāωāϜāĻžāϰ āϕ⧇āĻŸā§‡ āĻĻ⧇āϝāĻŧ err := ctx.Err() fmt.Println("Request canceled by user:", err) http.Error(w, err.Error(), http.StatusRequestTimeout) } }

ā§Ē. Production Pattern: Database Timeout (Crucial)

āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ⧇ āĻ•āĻ–āύ⧋ db.Query āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ āύāĻž, āϏāĻ°ā§āĻŦāĻĻāĻž db.QueryContext āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύāĨ¤ āĻāϟāĻŋ āĻĄā§‡āϟāĻžāĻŦ⧇āϏ āĻšā§āϝāĻžāĻ‚ āĻšāĻ“ā§ŸāĻž āĻĨ⧇āϕ⧇ āĻŦāĻžāρāϚāĻžā§ŸāĨ¤

func getUser(ctx context.Context, db *sql.DB, id int) { // ā§§. āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ context āĻĨ⧇āϕ⧇ āύāϤ⧁āύ context, āϝāĻžāϰ āĻŽā§‡āϝāĻŧāĻžāĻĻ āĻŽāĻžāĻ¤ā§āϰ ā§Ģā§Ļ āĻŽāĻŋāϞāĻŋ-āϏ⧇āϕ⧇āĻ¨ā§āĻĄ queryCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond) defer cancel() // āĻ…āĻŦāĻļā§āϝāχ āĻ•āϞ āĻ•āϰāĻŦ⧇āύ // ⧍. QueryContext āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ // āϝāĻĻāĻŋ ā§Ģā§Ļms-āĻāϰ āĻŽāĻ§ā§āϝ⧇ DB āωāĻ¤ā§āϤāϰ āύāĻž āĻĻ⧇āϝāĻŧ, āĻāϟāĻŋ āĻ…āĻŸā§‹āĻŽā§‡āϟāĻŋāĻ• āĻ•ā§āϝāĻžāĻ¨ā§āϏ⧇āϞ āĻšāĻŦ⧇ row := db.QueryContext(queryCtx, "SELECT name FROM users WHERE id=?", id) // ... scan and return }

ā§Ģ. Context Values: The Dark Side (āϏāϤāĻ°ā§āĻ•āϤāĻž)

context.WithValue āϖ⧁āĻŦ āĻŦāĻŋāϤāĻ°ā§āĻ•āĻŋāϤāĨ¤ āĻāϟāĻŋ āĻ…āύ⧇āĻ•āϟāĻž āĻ—ā§āϞ⧋āĻŦāĻžāϞ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ āĻŽāϤ⧋āĨ¤

❌ āϝāĻž āĻ•āĻ–āύ⧋ Context-āĻ āϰāĻžāĻ–āĻŦ⧇āύ āύāĻž:

  • Database Connection
  • Logger objects
  • Configuration
  • āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āĻ°ā§Ÿā§‹āϜāĻ¨ā§€ā§Ÿ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ (āϝ⧇āĻŽāύ username, orderID)

✅ āϝāĻž Context-āĻ āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύ (Request Scoped Meta):

  • Trace ID / Request ID (āϞāĻ— āĻŸā§āϰ⧇āϏāĻŋāĻ‚ā§Ÿā§‡āϰ āϜāĻ¨ā§āϝ)
  • User ID / Role ( āĻ…āĻĨ⧇āĻ¨ā§āϟāĻŋāϕ⧇āĻļāύ āĻŽāĻŋāĻĄāϞāĻ“ā§Ÿā§āϝāĻžāϰ āĻĨ⧇āϕ⧇)
  • IP Address

Best Practice Code:

// Key-āĻāϰ āϜāĻ¨ā§āϝ āφāϞāĻžāĻĻāĻž type āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ āϝāĻžāϤ⧇ collision āύāĻž āĻšāϝāĻŧ type key int const userKey key = 1 // Value āϏ⧇āϟ āĻ•āϰāĻž func WithUser(ctx context.Context, u *User) context.Context { return context.WithValue(ctx, userKey, u) } // Value āĻŦ⧇āϰ āĻ•āϰāĻž func UserFrom(ctx context.Context) (*User, bool) { u, ok := ctx.Value(userKey).(*User) return u, ok }

ā§Ŧ. Advanced: Detached Context (Fire and Forget)

āĻŽāĻžāĻā§‡āĻŽāĻ§ā§āϝ⧇ āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ āϰāĻŋāĻ•ā§‹ā§Ÿā§‡āĻ¸ā§āϟ āĻļ⧇āώ āĻšā§Ÿā§‡ āϗ⧇āϞ⧇āĻ“ āφāĻŽāĻžāĻĻ⧇āϰ āĻ•āĻŋāϛ⧁ āĻ•āĻžāϜ (āϝ⧇āĻŽāύ: āϞāĻ— āϏ⧇āĻ­ āĻ•āϰāĻž, āĻŽā§‡āĻŸā§āϰāĻŋāĻ•ā§āϏ āĻĒāĻžāĻ āĻžāύ⧋) āϚāĻžāϞāĻŋā§Ÿā§‡ āϝ⧇āϤ⧇ āĻšā§ŸāĨ¤ āϤāĻ–āύ WithoutCancel (Go 1.21+) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§ŸāĨ¤

func mainHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // āϏāĻžāϧāĻžāϰāĻŖ āĻ•āĻžāϜ processData(ctx) // āϰāĻŋāϕ⧋āϝāĻŧ⧇āĻ¸ā§āϟ āĻļ⧇āώ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻŽāϰāĻž āϞāĻ— āϏ⧇āĻ­ āĻ•āϰāϤ⧇ āϚāĻžāχ // āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ (ctx) āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšāϞ⧇āĻ“ āĻāϟāĻŋ āĻ•ā§āϝāĻžāύāϏ⧇āϞ āĻšāĻŦ⧇ āύāĻž go saveAuditLog(context.WithoutCancel(ctx)) }

📝 Production Checklist for Context

āϕ⧋āĻĄ āϰāĻŋāĻ­āĻŋāω āĻ•āϰāĻžāϰ āϏāĻŽā§Ÿ āĻāχ āĻĒā§Ÿā§‡āĻ¨ā§āϟāϗ⧁āϞ⧋ āĻšā§‡āĻ• āĻ•āϰ⧁āύ:

  1. First Parameter: ctx āĻ•āĻŋ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āφāϛ⧇? (āĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āĻĒā§āĻ°ā§āϝāĻžāĻ•āϟāĻŋāϏ)āĨ¤
  2. Struct Field: Context āĻ•āĻŋ āϕ⧋āύ⧋ struct-āĻāϰ āϭ⧇āϤāϰ⧇ āĻĢāĻŋāĻ˛ā§āĻĄ āĻšāĻŋāϏ⧇āĻŦ⧇ āϰāĻžāĻ–āĻž āĻšā§Ÿā§‡āϛ⧇? (Never do this!)āĨ¤ Context āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻ•āϞ⧇ āĻĒāĻžāϏ āĻ•āϰāϤ⧇ āĻšā§ŸāĨ¤
  3. Cancel Call: WithTimeout āĻŦāĻž WithCancel āĻ•āϞ āĻ•āϰāĻžāϰ āĻ āĻŋāĻ• āĻĒāϰ⧇āχ defer cancel() āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āϛ⧇ āϤ⧋? (āύāĻž āĻšāϞ⧇ āĻŽā§‡āĻŽāϰāĻŋ āϞāĻŋāĻ• āĻšāĻŦ⧇)āĨ¤
  4. Nil Context: āϕ⧋āĻĨāĻžāĻ“ āĻ•āĻŋ nil āĻĒāĻžāϏ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇? nil āĻāϰ āĻŦāĻĻāϞ⧇ context.TODO() āĻŦāĻž context.Background() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤
  5. Monitor: select { case <-ctx.Done(): ... } āĻĻāĻŋā§Ÿā§‡ āĻ•āĻŋ āϞāĻ‚ āϰāĻžāύāĻŋāĻ‚ āĻĒā§āϰāϏ⧇āϏ āĻŽāύāĻŋāϟāϰ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇?

🆚 Context vs Channels (āĻ•āύāĻĢāĻŋāωāĻļāύ āĻĻā§‚āϰ⧀āĻ•āϰāĻŖ)

āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝContextChannels
āĻŽā§‚āϞ āĻ•āĻžāϜSignaling & Lifecycle Management (āĻ•āĻ–āύ āĻ•āĻžāϜ āĻĨāĻžāĻŽāĻŦ⧇)āĨ¤Data Flow (āĻĄā§‡āϟāĻž āφāĻĻāĻžāύ-āĻĒā§āϰāĻĻāĻžāύ)āĨ¤
Data TypesāĻŽā§‡āϟāĻžāĻĄā§‡āϟāĻž (Request ID, Token)āĨ¤āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ⧇āϰ āφāϏāϞ āĻĄā§‡āϟāĻž (Struct, Int, String)āĨ¤
DirectionāωāĻĒāϰ āĻĨ⧇āϕ⧇ āύāĻŋāĻšā§‡ (Parent → Child)āĨ¤āĻĻ⧁āχ āĻĻāĻŋāϕ⧇āχ āĻšāϤ⧇ āĻĒāĻžāϰ⧇ (āĻ•āĻŋāĻ¨ā§āϤ⧁ āϏāĻžāϧāĻžāϰāĻŖāϤ Unidirectional āĻ­āĻžāϞ⧋)āĨ¤

💡 Final Pro Tip for Interviews

āϝāĻĻāĻŋ āĻĒā§āϰāĻļā§āύ āĻ•āϰ⧇: “Go āϤ⧇ Context āϕ⧇āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿ?”

āωāĻ¤ā§āϤāϰ: > “Context āĻŽā§‚āϞāϤ āϤāĻŋāύāϟāĻŋ āĻ•āĻžāĻœā§‡āϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ:

ā§§. Timeout & Cancellation Control (āϝāĻžāϤ⧇ Goroutine leak āύāĻž āĻšāϝāĻŧ)āĨ¤ ⧍. Propagation (āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ āĻĒā§āϰāϏ⧇āϏ āĻŦāĻ¨ā§āϧ āĻšāϞ⧇ āϚāĻžāχāĻ˛ā§āĻĄ āĻĒā§āϰāϏ⧇āϏāϗ⧁āϞ⧋āĻ“ āϝāĻžāϤ⧇ āĻŦāĻ¨ā§āϧ āĻšāϝāĻŧ)āĨ¤ ā§Š. Request Scoped Values āĻĒāĻžāϏ āĻ•āϰāĻž (āϝ⧇āĻŽāύ Trace ID)āĨ¤â€