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

Day 4: Select Statement & Multiplexing

select-āϕ⧇ āφāĻĒāύāĻŋ goroutine-āĻĻ⧇āϰ “āĻŸā§āϰāĻžāĻĢāĻŋāĻ• āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞāĻžāĻ°â€ āĻŦāϞāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ goroutine-āϕ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āωāĻĒāϰ āĻāĻ•āĻŦāĻžāϰ⧇ āύāϜāϰ āϰāĻžāĻ–āϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϝ⧇āϟāĻŋ āφāϗ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ (ready) āĻšā§Ÿ, āϏ⧇āϟāĻŋāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤

🧠 āĻ•āύāϏ⧇āĻĒā§āϟ āĻŦā§‹āĻāĻž

🤔 select āϕ⧇āύ āĻĒā§āϰāϝāĻŧā§‹āϜāύ?

āϧāϰ⧁āύ, āφāĻĒāύāĻžāϰ āĻĻ⧁āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ āφāϛ⧇, ch1 āĻāĻŦāĻ‚ ch2āĨ¤ āφāĻĒāύāĻŋ āĻĻ⧁āĻŸā§‹ āĻĨ⧇āϕ⧇āχ āĻĄā§‡āϟāĻž āφāĻļāĻž āĻ•āϰāϛ⧇āύāĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāĻ­āĻžāĻŦ⧇ āϞ⧇āϖ⧇āύ:

data1 := <-ch1 // āĻāĻ–āĻžāύ⧇ āφāϟāϕ⧇ āϗ⧇āϞ data2 := <-ch2 // āĻāϟāĻŋ āφāϰ āϚāϞāĻŦ⧇ āύāĻž, āϝāĻĻāĻŋ ch1 āĻ āĻĄā§‡āϟāĻž āύāĻž āφāϏ⧇

āϝāĻĻāĻŋ ch1-āĻ āϕ⧋āύ⧋ āĻĄā§‡āϟāĻž āύāĻž āφāϏ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ ch2-āϤ⧇ āĻĄā§‡āϟāĻž āϚāϞ⧇ āφāϏ⧇, āϤāĻŦ⧁āĻ“ āφāĻĒāύāĻžāϰ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ đŸ”Ĩch1-āĻāϰ āϜāĻ¨ā§āϝ āĻ…āύāĻ¨ā§āϤāĻ•āĻžāϞ āĻ…āĻĒ⧇āĻ•ā§āώāĻž (block) āĻ•āϰāϤ⧇ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤đŸ”Ĩ

select āĻāχ āϏāĻŽāĻ¸ā§āϝāĻžāϰ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰ⧇āĨ¤ āĻāϟāĻŋ āϏāĻŦ āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āĻĻāĻŋāϕ⧇ “āϤāĻžāĻ•āĻŋā§Ÿā§‡â€ āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āϝ⧇ āĻšā§āϝāĻžāύ⧇āϞāϟāĻŋ āĻĒā§āϰāĻĨāĻŽ āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāϤ⧇ āĻŦāĻž āĻ—ā§āϰāĻšāĻŖ āĻ•āϰāϤ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻšā§Ÿ, āϏ⧇āϟāĻŋāϰ āϕ⧋āĻĄ āĻŦā§āϞāĻ•āϟāĻŋ āϚāĻžāϞāĻžāϝāĻŧāĨ¤


🔹 1. select āϕ⧀ āĻ•āϰ⧇ āĻāĻŦāĻ‚ select āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ

select āĻ…āύ⧇āĻ•āϟāĻž switch āĻāϰ āĻŽāϤ⧋, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāϟāĻŋ āĻ•āĻžāϜ āĻ•āϰ⧇ āĻšā§āϝāĻžāύ⧇āϞ āĻ…āĻĒāĻžāϰ⧇āĻļāύ (send/receive) āĻāϰ āωāĻĒāϰāĨ¤

👉 āĻ•āĻžāϜ: āĻāĻ•āĻžāϧāĻŋāĻ• āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āϝ⧇ āĻšā§āϝāĻžāύ⧇āϞ āφāϗ⧇ ready āĻšā§Ÿ, āϏ⧇āϟāĻžāϰ case execute āĻšā§ŸāĨ¤

📜 select āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻāĻŦāĻ‚ “First Ready Wins”

select-āĻāϰ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ switch-āĻāϰ āĻŽāϤ⧋āχāĨ¤

select { case data := <-ch1: // ch1 āĻĨ⧇āϕ⧇ āĻĄā§‡āϟāĻž āϰāĻŋāϏāĻŋāĻ­ āĻšāϞ⧇ āĻāϟāĻŋ āϚāϞāĻŦ⧇ fmt.Println("ch1 āĻĨ⧇āϕ⧇ āĻĒ⧇āϞāĻžāĻŽ:", data) case ch2 <- "Hi": // ch2-āϤ⧇ āĻĄā§‡āϟāĻž āϏ⧇āĻ¨ā§āĻĄ āĻ•āϰāĻž āϏāĻŽā§āĻ­āĻŦ āĻšāϞ⧇ āĻāϟāĻŋ āϚāϞāĻŦ⧇ fmt.Println("ch2-āϤ⧇ 'Hi' āĻĒāĻžāĻ āĻžāϞāĻžāĻŽ") case <-ch3: // ch3 āĻĨ⧇āϕ⧇ āĻĄā§‡āϟāĻž āϰāĻŋāϏāĻŋāĻ­ āĻšāϞ⧇ (āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻĄā§‡āϟāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻ•āϰāϞ⧇) fmt.Println("ch3 āĻĨ⧇āϕ⧇ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒ⧇āϞāĻžāĻŽ") }

đŸšĻ āϚāĻŋāĻ¤ā§āϰ: select āϝ⧇āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇

select āĻ¸ā§āĻŸā§‡āϟāĻŽā§‡āĻ¨ā§āϟāϕ⧇ āĻāĻ•āϟāĻŋ āĻĢāĻžāύ⧇āϞ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ­āĻžāĻŦ⧁āύ:

[goroutine] | <--select--> / | \ / | \ (āĻ…āĻĒ⧇āĻ•ā§āώāĻž) (āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ) (āĻ…āĻĒ⧇āĻ•ā§āώāĻž) | | | [ch1] [ch2] [ch3]
  • select āϤāĻŋāύāϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āĻĻāĻŋāϕ⧇āχ āύāϜāϰ āϰāĻžāϖ⧇āĨ¤
  • āϧāϰ⧁āύ, ch2 āĻĒā§āϰāĻĨāĻŽā§‡ āĻĄā§‡āϟāĻž āϰāĻŋāϏāĻŋāĻ­ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻšāϞ⧋āĨ¤
  • select āĻ…āĻŦāĻŋāϞāĻŽā§āĻŦ⧇ ch2-āĻāϰ case āĻŦā§āϞāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰāĻŦ⧇ āĻāĻŦāĻ‚ āϚāĻžāϞāĻžāĻŦ⧇āĨ¤ āĻ…āĻ¨ā§āϝ case-āϗ⧁āϞ⧋ āωāĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤
  • “First Ready Wins”: āĻāϟāĻŋāχ āĻŽā§‚āϞ āύāĻŋāϝāĻŧāĻŽāĨ¤ āϝ⧇ āĻĒā§āϰāĻĨāĻŽ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻšāĻŦ⧇, āϏ⧇āχ āϜāĻŋāϤāĻŦ⧇āĨ¤
  • āϝāĻĻāĻŋ āĻāĻ•āĻžāϧāĻŋāĻ• case āĻāĻ•āχ āϏāĻžāĻĨ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻĨāĻžāϕ⧇ (āϖ⧁āĻŦ āĻŦāĻŋāϰāϞ, āϤāĻŦ⧇ āϏāĻŽā§āĻ­āĻŦ), select āϤāĻ–āύ āϤāĻžāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āĻĨ⧇āϕ⧇ āĻāϞ⧋āĻŽā§‡āϞ⧋āĻ­āĻžāĻŦ⧇ (randomly) āĻāĻ•āϟāĻŋāϕ⧇ āĻŦ⧇āϛ⧇ āύ⧇āϝāĻŧāĨ¤ āĻāϟāĻŋ āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āĻĒā§āϰāϤāĻŋ āĻĒāĻ•ā§āώāĻĒāĻžāϤ (bias) āĻĻā§‚āϰ āĻ•āϰāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤

🔹 2. select āĻāϰ āϰ⧁āϞ: “First Ready Wins”

  • āĻāĻ•āĻžāϧāĻŋāĻ• āĻšā§āϝāĻžāύ⧇āϞ ready āĻĨāĻžāĻ•āϞ⧇ → Go āĻ°â€ā§āϝāĻžāĻ¨ā§āĻĄāĻŽāϞāĻŋ āĻāĻ•āϟāĻŋ āĻŦ⧇āϛ⧇ āĻ¨ā§‡ā§ŸāĨ¤
  • āϕ⧋āύ⧋ āĻšā§āϝāĻžāύ⧇āϞ ready āύāĻž āĻĨāĻžāĻ•āϞ⧇ → āĻŦā§āϞāĻ• āĻ•āϰ⧇ (āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇)āĨ¤
  • āϝāĻĻāĻŋ default āĻĨāĻžāϕ⧇ → āĻŦā§āϞāĻ• āĻ•āϰ⧇ āύāĻžāĨ¤
  • āĻāĻ•āĻŦāĻžāϰ⧇ āĻļ⧁āϧ⧁ āĻāĻ•āϟāĻžāχ case āϚāϞ⧇āĨ¤

🔹 3. 💨 āύāύ-āĻŦā§āϞāĻ•āĻŋāĻ‚ āĻ…āĻĒāĻžāϰ⧇āĻļāύ: default

āϝāĻĻāĻŋ āφāĻĒāύāĻŋ āϚāĻžāύ āϝ⧇ select āϕ⧋āύ⧋ āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟ⧁āĻ“ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āύāĻž āĻ•āϰ⧁āĻ•, āϤāĻŦ⧇ default āϕ⧇āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

🧩 default āϕ⧇āϏ āϤāĻ–āύāχ āϚāϞ⧇ āϝāĻ–āύ āĻ…āĻ¨ā§āϝ āϕ⧋āύ⧋ case āϤāĻžā§ŽāĻ•ā§āώāĻŖāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ āĻĨāĻžāϕ⧇ āύāĻžāĨ¤

select { case data := <-ch: fmt.Println("āĻĄā§‡āϟāĻž āϰāĻŋāϏāĻŋāĻ­āĻĄ:", data) default: // āϕ⧋āύ⧋ āĻšā§āϝāĻžāύ⧇āϞ āϰ⧇āĻĄāĻŋ āύāĻž āĻĨāĻžāĻ•āϞ⧇ āĻāϟāĻŋ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āϚāϞāĻŦ⧇ fmt.Println("āĻāĻ–āύ⧋ āϕ⧋āύ⧋ āĻĄā§‡āϟāĻž āύ⧇āχ, āφāĻŽāĻŋ āĻ…āĻ¨ā§āϝ āĻ•āĻžāϜ āĻ•āϰāĻ›āĻŋ...") }

āĻāϟāĻŋ “try-receive” āĻŦāĻž “non-blocking receive” āĻ•āϰāĻžāϰ āĻāĻ•āϟāĻŋ āϏāĻšāϜ āωāĻĒāĻžāϝāĻŧāĨ¤


🔹 4. âŗ time.After āĻĻāĻŋā§Ÿā§‡ āϟāĻžāχāĻŽāφāωāϟ (Timeout)

āĻ…āύ⧇āĻ• āϏāĻŽā§Ÿ āφāĻŽāϰāĻž āĻ…āύāĻ¨ā§āϤāĻ•āĻžāϞ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāϤ⧇ āϚāĻžāχ āύāĻžāĨ¤ āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋāĨ¤ time.After(duration) āĻāĻ•āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇, āϝāĻž āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ (duration) āĻĒāĻžāϰ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰ āĻāĻ•āϟāĻŋ āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāϝāĻŧāĨ¤

āĻāϟāĻŋ select-āĻāϰ āϏāĻžāĻĨ⧇ āϟāĻžāχāĻŽāφāωāϟ āϤ⧈āϰāĻŋāϰ āϜāĻ¨ā§āϝ āĻĻ⧁āĻ°ā§āĻĻāĻžāĻ¨ā§āϤ:

select { case data := <-longRunningTaskCh: fmt.Println("āĻ•āĻžāϜ āϏāĻŽā§āĻĒāĻ¨ā§āύ:", data) case <-time.After(2 * time.Second): // 2 āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻĒāĻžāϰ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇ āĻāϟāĻŋ āϚāϞāĻŦ⧇ fmt.Println("āϟāĻžāχāĻŽāφāωāϟ! āφāϰ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻž āϏāĻŽā§āĻ­āĻŦ āύāĻžāĨ¤") }

āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻ•ā§āϞāĻžāϏāĻŋāĻ• āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ: āĻšāϝāĻŧ āĻ•āĻžāϜāϟāĻŋ āϏāĻŽā§āĻĒāĻ¨ā§āύ āĻšāĻŦ⧇, āĻ…āĻĨāĻŦāĻž āϟāĻžāχāĻŽāφāωāϟ āĻšāĻŦā§‡â€”āĻĻ⧁āϟāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ đŸ”Ĩāϝ⧇āϟāĻŋ āφāϗ⧇ āϘāϟāĻŦ⧇āĨ¤đŸ”Ĩ


🔀 āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ: āĻĢā§āϝāĻžāύ-āχāύ (Fan-In) / āĻŽāĻžāĻ˛ā§āϟāĻŋāĻĒā§āϞ⧇āĻ•ā§āϏāĻŋāĻ‚

āĻĢā§āϝāĻžāύ-āχāύ āĻšāϞ⧋ āĻāĻŽāύ āĻāĻ•āϟāĻŋ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āϝ⧇āĻ–āĻžāύ⧇ āφāĻĒāύāĻŋ āĻāĻ•āĻžāϧāĻŋāĻ• āχāύāĻĒ⧁āϟ āĻšā§āϝāĻžāύ⧇āϞ āĻĨ⧇āϕ⧇ āĻĄā§‡āϟāĻž āύāĻŋāϝāĻŧ⧇ āĻāĻ•āϟāĻŋāĻŽāĻžāĻ¤ā§āϰ āφāωāϟāĻĒ⧁āϟ āĻšā§āϝāĻžāύ⧇āϞ⧇ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇āύāĨ¤ āĻāϟāĻŋ select-āĻāϰ āĻāĻ•āϟāĻŋ āϖ⧁āĻŦ āϏāĻžāϧāĻžāϰāĻŖ āĻŦā§āϝāĻŦāĻšāĻžāϰāĨ¤

āϧāϰ⧁āύ, āφāĻĒāύāĻžāϰ āĻĻ⧁āϟāĻŋ āϏ⧋āĻ°ā§āϏ (producer) āφāϛ⧇, āϝāĻžāϰāĻž āĻĒā§āϰāĻ¤ā§āϝ⧇āϕ⧇ āύāĻŋāĻœā§‡āĻĻ⧇āϰ āĻšā§āϝāĻžāύ⧇āϞ⧇ āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāĻšā§āϛ⧇āĨ¤ āφāĻĒāύāĻŋ āϏ⧇āχ āĻĻ⧁āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞāϕ⧇ “merge” āĻ•āϰ⧇ āĻāĻ•āϟāĻŋ āĻšā§āϝāĻžāύ⧇āϞ⧇ āφāύāϤ⧇ āϚāĻžāύāĨ¤

āφāĻŽāϰāĻž āĻāχ āĻ•āĻžāϜāϟāĻŋ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋāĨ¤

đŸ’ģ Exercises

⚡ Example 1: Two Channels, First Ready Wins

package main import ( "fmt" "time" ) func main() { ch1 := make(chan string) ch2 := make(chan string) go func() { time.Sleep(1 * time.Second) ch1 <- "🍎 From channel 1" }() go func() { time.Sleep(2 * time.Second) ch2 <- "🍌 From channel 2" }() select { case msg1 := <-ch1: fmt.Println(msg1) case msg2 := <-ch2: fmt.Println(msg2) } }

đŸ’Ŧ āĻĒā§āϰāĻļā§āύ ā§§: go routine āĻĨāĻžāĻ•āĻž āϏāĻ¤ā§āĻ¤ā§āĻŦ⧇āĻ“ āφāĻŽāϰāĻž āϕ⧇āύ WaitGroup āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŋāύāĻŋ?

āωāĻ¤ā§āϤāϰ: āĻ•āĻžāϰāĻŖ select āύāĻŋāĻœā§‡āχ channel āĻĨ⧇āϕ⧇ data āĻĒāĻžāĻ“ā§ŸāĻžāϰ āϜāĻ¨ā§āϝ āĻŦā§āϞāĻ• āĻ•āϰ⧇ āĻĨāĻžāϕ⧇āĨ¤ āϝāϤāĻ•ā§āώāĻŖ āύāĻž āϕ⧋āύ⧋ āĻšā§āϝāĻžāύ⧇āϞ ready āĻšā§Ÿ, main goroutine āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇āĨ¤ āĻ…āĻ°ā§āĻĨāĻžā§Ž main āφāϗ⧇āĻ­āĻžāϗ⧇ terminate āĻšā§Ÿ āύāĻžāĨ¤

WaitGroup āĻĻāϰāĻ•āĻžāϰ āĻšā§Ÿ āϝāĻ–āύ:

  • āϕ⧋āύ⧋ channel āύ⧇āχ, āĻļ⧁āϧ⧁ goroutine āϚāϞāϛ⧇, āĻ…āĻĨāĻŦāĻž
  • āϤ⧁āĻŽāĻŋ manualāĻ­āĻžāĻŦ⧇ goroutine āĻļ⧇āώ āĻšāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāϤ⧇ āϚāĻžāĻ“āĨ¤

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

// select āύāĻŋāĻœā§‡āχ āĻŦā§āϞāĻ• āĻ•āϰāĻŦ⧇ select { case msg := <-ch: fmt.Println(msg) } // WaitGroup āĻĻāϰāĻ•āĻžāϰ āϝāĻ–āύ āϕ⧋āύ⧋ channel āύ⧇āχ var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() fmt.Println("working...") }() wg.Wait()

✅ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ: āϝāĻ–āύ select āĻŦāĻž <-ch āφāϛ⧇ → main goroutine āύāĻŋāĻœā§‡āχ wait āĻ•āϰ⧇ → WaitGroup āĻĻāϰāĻ•āĻžāϰ āύ⧇āχāĨ¤

đŸ’Ŧ āĻĒā§āϰāĻļā§āύ ⧍: āϕ⧇āύ go routine āϏāϰāĻŋāϝāĻŧ⧇ āĻĻāĻŋāϞ⧇āĻ“ āϕ⧋āĻĄā§‡ “fatal error: all goroutines are asleep - deadlock!” āφāϏ⧇?

āωāĻ¤ā§āϤāϰ: āĻ•āĻžāϰāĻŖ āϕ⧋āύ⧋ goroutine āĻšā§āϝāĻžāύ⧇āϞ⧇ data āĻĒāĻžāĻ āĻžāĻšā§āϛ⧇ āύāĻž, āĻ…āĻĨāϚ select āĻšā§āϝāĻžāύ⧇āϞ āĻĨ⧇āϕ⧇ data receive āĻ•āϰāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāϛ⧇āĨ¤

ch1 := make(chan string) ch2 := make(chan string) select { case msg1 := <-ch1: fmt.Println(msg1) case msg2 := <-ch2: fmt.Println(msg2) }

👉 āĻāĻ–āĻžāύ⧇:

  • ch1 āĻ“ ch2 āĻĨ⧇āϕ⧇ āϕ⧇āω send āĻ•āϰāϛ⧇ āύāĻžāĨ¤
  • select āĻĻ⧁āχāϟāĻŋāϤ⧇āχ receive āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāϛ⧇āĨ¤
  • āĻĢāϞ⧇ main goroutine āĻŦā§āϞāĻ• āĻšā§Ÿā§‡ āϝāĻžā§Ÿ āĻāĻŦāĻ‚ āĻ…āĻ¨ā§āϝ āϕ⧋āύ⧋ goroutineāĻ“ āϚāϞāϛ⧇ āύāĻžāĨ¤

Go runtime āĻŦ⧁āĻā§‡ āϝāĻžā§Ÿ “āϏāĻŦāĻžāχ āϘ⧁āĻŽāĻŋā§Ÿā§‡ āφāĻ›ā§‡â€ 😴 āϤāĻ–āύ panic āĻĻā§‡ā§Ÿ:

fatal error: all goroutines are asleep - deadlock!

✅ āϏāĻŽāĻžāϧāĻžāύ: āĻāĻ•āϟāĻž goroutine āĻĨ⧇āϕ⧇ data āĻĒāĻžāĻ āĻžāĻ“ āĻŦāĻž buffered channel āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧋āĨ¤

go func() { ch1 <- "🍎 From channel 1" }() go func() { ch2 <- "🍌 From channel 2" }()

āĻ…āĻĨāĻŦāĻž

ch1 := make(chan string, 1) ch1 <- "🍎 From buffered channel" select { case msg := <-ch1: fmt.Println(msg) }

🧠 āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ: Deadlock āĻšā§Ÿ āϝāĻ–āύ āϏāĻŦāĻžāχ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϕ⧇āω āĻ•āĻžāϜ āĻ•āϰ⧇ āύāĻžāĨ¤

💡 Deadlock Rule āϏāĻšāϜāĻ­āĻžāĻŦ⧇

āĻ…āĻŦāĻ¸ā§āĻĨāĻžāĻĢāϞāĻžāĻĢāϞ
Channel āĻĨ⧇āϕ⧇ receive āĻšāĻšā§āϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϕ⧇āω send āĻ•āϰāϛ⧇ āύāĻžDeadlock
Channel-āĻ send āĻšāĻšā§āϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϕ⧇āω receive āĻ•āϰāϛ⧇ āύāĻžDeadlock
Unbuffered channel → send & receive āĻāĻ•āϏāĻžāĻĨ⧇ āύāĻž āĻšāϞ⧇Deadlock
Buffered channel → capacity āĻļ⧇āώ āĻšā§Ÿā§‡ āϗ⧇āϞ⧇ send āĻŦā§āϞāĻ• āĻšāĻŦ⧇Possible Deadlock

âš™ī¸ Example 2: Add Default Case (Non-blocking)

select { case msg := <-ch1: fmt.Println("Received:", msg) default: fmt.Println("No channel ready — moving on 🚀") }

⏰ Example 3: Add Timeout

select { case msg := <-ch1: fmt.Println("Got:", msg) case <-time.After(2 * time.Second): fmt.Println("Timeout! ⏰ No data received.") }

🧩 Bonus: Context Cancellation

āϝāĻĻāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽā§Ÿ āĻĒāϰ⧇ āϏāĻŦ āĻŦāĻ¨ā§āϧ āĻ•āϰāϤ⧇ āϚāĻžāĻ“ 👇

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() for { select { case msg := <-out: fmt.Println(msg) case <-ctx.Done(): fmt.Println("🛑 Stopped by context timeout.") return } }

🧾 Mini Cheat Sheet — select Quick Recall

FeatureSyntaxBehavior
Basic selectselect { case msg := <-ch: }Waits for any ready channel
Default casedefault:Prevents blocking
Timeoutcase <-time.After(d):Triggers after duration
Fan-inCombine multiple channelsUse select inside goroutine
Context cancelcase <-ctx.Done():Stop gracefully
Rule“First ready wins”Random if multiple ready

🧠 Summary (āĻŦāĻžāĻ‚āϞāĻžā§Ÿ āϏāĻžāϰāĻžāĻ‚āĻļ)

  • select āĻāĻ•āĻžāϧāĻŋāĻ• āĻšā§āϝāĻžāύ⧇āϞ āĻāĻ•āϏāĻžāĻĨ⧇ āĻŽāύāĻŋāϟāϰ āĻ•āϰ⧇āĨ¤
  • āϝ⧇ āĻšā§āϝāĻžāύ⧇āϞ āφāϗ⧇ ready āĻšā§Ÿ, āϏ⧇āϟāĻžāϰ case āϚāĻžāϞ⧁ āĻšā§ŸāĨ¤
  • default case āĻĻāĻŋāϞ⧇ āĻŦā§āϞāĻ• āĻšā§Ÿ āύāĻžāĨ¤
  • time.After āĻĻāĻŋā§Ÿā§‡ timeout āϏ⧇āϟ āĻ•āϰāĻž āϝāĻžā§ŸāĨ¤
  • Fan-in pattern āĻĻāĻŋā§Ÿā§‡ āĻāĻ•āĻžāϧāĻŋāĻ• channel merge āĻ•āϰāĻž āϝāĻžā§ŸāĨ¤
  • context.WithTimeout āĻĻāĻŋā§Ÿā§‡ clean stop āĻ•āϰāĻž āϝāĻžā§ŸāĨ¤