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 āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŋāύāĻŋ?
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
| Feature | Syntax | Behavior |
|---|---|---|
| Basic select | select { case msg := <-ch: } | Waits for any ready channel |
| Default case | default: | Prevents blocking |
| Timeout | case <-time.After(d): | Triggers after duration |
| Fan-in | Combine multiple channels | Use select inside goroutine |
| Context cancel | case <-ctx.Done(): | Stop gracefully |
| Rule | âFirst ready winsâ | Random if multiple ready |
đ§ Summary (āĻŦāĻžāĻāϞāĻžā§ āϏāĻžāϰāĻžāĻāĻļ)
selectāĻāĻāĻžāϧāĻŋāĻ āĻā§āϝāĻžāύā§āϞ āĻāĻāϏāĻžāĻĨā§ āĻŽāύāĻŋāĻāϰ āĻāϰā§āĨ¤- āϝ⧠āĻā§āϝāĻžāύā§āϞ āĻāĻā§ ready āĻšā§, āϏā§āĻāĻžāϰ case āĻāĻžāϞ⧠āĻšā§āĨ¤
defaultcase āĻĻāĻŋāϞ⧠āĻŦā§āϞāĻ āĻšā§ āύāĻžāĨ¤time.AfterāĻĻāĻŋā§ā§ timeout āϏā§āĻ āĻāϰāĻž āϝāĻžā§āĨ¤- Fan-in pattern āĻĻāĻŋā§ā§ āĻāĻāĻžāϧāĻŋāĻ channel merge āĻāϰāĻž āϝāĻžā§āĨ¤
context.WithTimeoutāĻĻāĻŋā§ā§ clean stop āĻāϰāĻž āϝāĻžā§āĨ¤