Skip to Content
Go Realm v1 is released 🎉
Go Routines🧭 Day 5

Context Cancellation, Timeout & Deadline

āĻ—āϤāĻŦāĻžāϰ āφāĻŽāϰāĻž select āĻĻāĻŋā§Ÿā§‡ āĻāĻ•āĻžāϧāĻŋāĻ• āĻšā§āϝāĻžāύ⧇āϞ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ āĻ•āϰāĻž āĻļāĻŋāϖ⧇āĻ›āĻŋāĨ¤ āφāϜ āφāĻŽāϰāĻž āĻļāĻŋāĻ–āĻŦā§‹ goroutine-āĻĻ⧇āϰ control āĻ•āϰāĻžāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻāĻŦāĻ‚ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ āϟ⧁āϞ: contextāĨ¤


🧠 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 āĻšā§Ÿ