Skip to Content
Go Realm v1 is released 🎉
Go RoutinesGo Channel

🍀 Go Channel

Go-āϤ⧇ Concurrency āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ āϟ⧁āϞ āĻšāϞ⧋ ChannelāĨ¤

Goroutine āϗ⧁āϞ⧋ āĻ¸ā§āĻŦāĻžāϧ⧀āύāĻ­āĻžāĻŦ⧇ āϚāϞ⧇, āϤāĻžāχ āϤāĻžāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ Safe Data Transfer āĻāĻŦāĻ‚ Synchronization āϜāĻ¨ā§āϝ āĻĻāϰāĻ•āĻžāϰ āĻšā§Ÿ āĻāĻ•āϟāĻŋ safe communication mechanismāĨ¤

Channel āĻšāĻšā§āϛ⧇ āϏ⧇āχ āύāĻŋāϰāĻžāĻĒāĻĻ āĻĒāĻžāχāĻĒāϞāĻžāχāύ, āϝ⧇āĻ–āĻžāύ⧇:

  • āĻāĻ• Goroutine āϤāĻĨā§āϝ āĻĒāĻžāĻ āĻžā§Ÿ (chan <-)
  • āĻ…āĻ¨ā§āϝ Goroutine āϤāĻĨā§āϝ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇ (<- chan)

channel āĻĻāĻŋā§Ÿā§‡ āĻ—ā§‹āϰ⧁āϟāĻŋāύāϗ⧁āϞ⧋ āĻāϕ⧇ āĻ…āĻĒāϰ⧇āϰ āϏāĻžāĻĨ⧇ “āĻ•āĻĨāĻž āĻŦāĻ˛ā§‡â€āĨ¤

Go Philosophy: “Do not communicate by sharing memory; instead, share memory by communicating.”


ā§§. Channel-āĻāϰ āϧāϰāĻŖ (Types of Channels)

Channel āĻĒā§āϰāϧāĻžāύāϤ āĻĻ⧁āχ āϧāϰāϪ⧇āϰ āĻšā§ŸāĨ¤ āĻāĻĻ⧇āϰ āφāϚāϰāĻŖ āĻŦā§‹āĻāĻž āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āϕ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āϜāϰ⧁āϰāĻŋāĨ¤

āĻ•. Unbuffered Channel (Synchronous)

āĻāϤ⧇ āϕ⧋āύ⧋ āĻĄā§‡āϟāĻž āϜāĻŽāĻž āϰāĻžāĻ–āĻžāϰ āĻ•ā§āώāĻŽāϤāĻž āύ⧇āχāĨ¤

  • Send: Sender āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāύ⧋āϰ āĻĒāϰ Receiver āϏ⧇āϟāĻŋ āĻ—ā§āϰāĻšāĻŖ āύāĻž āĻ•āϰāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇ (Block āĻšāϝāĻŧ)āĨ¤
  • Receive: Receiver āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇ āϝāϤāĻ•ā§āώāĻŖ āύāĻž Sender āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāϝāĻŧāĨ¤
  • āĻŦā§āϝāĻŦāĻšāĻžāϰ: āϝāĻ–āύ āφāĻĒāύāĻŋ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāϤ⧇ āϚāĻžāύ āϝ⧇ āĻĄā§‡āϟāĻž āĻĒā§āϰāϏ⧇āϏ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰāχ āĻĒāϰ⧇āϰ āϧāĻžāĻĒ⧇ āϝāĻžāĻŦ⧇ (Perfect Synchronization)āĨ¤

āωāĻĻāĻžāĻšāϰāĻŖ - Unbuffered Channel:

package main import ( "fmt" "time" ) func main() { ch := make(chan string) // Unbuffered channel go func() { fmt.Println("Goroutine: Sending data...") ch <- "Hello" // āĻāĻ–āĻžāύ⧇ block āĻšāĻŦ⧇ āϝāϤāĻ•ā§āώāĻŖ āύāĻž main goroutine receive āĻ•āϰ⧇ fmt.Println("Goroutine: Data sent!") }() time.Sleep(2 * time.Second) // ⧍ āϏ⧇āϕ⧇āĻ¨ā§āĻĄ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻŋ fmt.Println("Main: Receiving data...") msg := <-ch // āĻāĻ–āύ goroutine unblock āĻšāĻŦ⧇ fmt.Println("Main: Received:", msg) } // Output: // Goroutine: Sending data... // (2 seconds pause) // Main: Receiving data... // Main: Received: Hello // Goroutine: Data sent!

āĻ–. Buffered Channel (Asynchronous)

āĻāϤ⧇ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻĒāϰāĻŋāĻŽāĻžāĻŖ āĻĄā§‡āϟāĻž āϜāĻŽāĻž āϰāĻžāĻ–āĻžāϰ āĻ•ā§āώāĻŽāϤāĻž (Capacity) āĻĨāĻžāϕ⧇āĨ¤

Buffer = Queue = Channel-āĻāϰ āϭ⧇āϤāϰ⧇ memoryāĨ¤

  • Send: āϝāϤāĻ•ā§āώāĻŖ āĻŦāĻžāĻĢāĻžāϰ (Buffer) āĻĒā§‚āĻ°ā§āĻŖ āύāĻž āĻšāϝāĻŧ, āϤāϤāĻ•ā§āώāĻŖ Sender āĻŦā§āϞāĻ• āĻšāϝāĻŧ āύāĻžāĨ¤
  • Receive: āϝāϤāĻ•ā§āώāĻŖ āĻŦāĻžāĻĢāĻžāϰ āĻ–āĻžāϞāĻŋ āύāĻž āĻšāϝāĻŧ, āϤāϤāĻ•ā§āώāĻŖ Receiver āĻŦā§āϞāĻ• āĻšāϝāĻŧ āύāĻžāĨ¤
  • āĻŦā§āϝāĻŦāĻšāĻžāϰ: āϝāĻ–āύ Sender āĻāĻŦāĻ‚ Receiver-āĻāϰ āĻ—āϤāĻŋāϰ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ āĻĨāĻžāϕ⧇ (Rate Limiting, Job Queue)āĨ¤

āωāĻĻāĻžāĻšāϰāĻŖ - Buffered Channel:

package main import "fmt" func main() { ch := make(chan int, 3) // Capacity 3 // Buffer āĻĒā§‚āĻ°ā§āĻŖ āύāĻž āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ block āĻšāĻŦ⧇ āύāĻž ch <- 1 fmt.Println("Sent: 1") ch <- 2 fmt.Println("Sent: 2") ch <- 3 fmt.Println("Sent: 3") // ch <- 4 // āĻāϟāĻž āĻ•āϰāϞ⧇ deadlock āĻšāĻŦ⧇, āĻ•āĻžāϰāĻŖ buffer āĻĒā§‚āĻ°ā§āĻŖ // Receive āĻ•āϰāĻŋ fmt.Println("Received:", <-ch) fmt.Println("Received:", <-ch) // āĻāĻ–āύ āφāĻŦāĻžāϰ send āĻ•āϰāĻž āϝāĻžāĻŦ⧇ ch <- 4 fmt.Println("Sent: 4") fmt.Println("Received:", <-ch) fmt.Println("Received:", <-ch) } // Output: // Sent: 1 // Sent: 2 // Sent: 3 // Received: 1 // Received: 2 // Sent: 4 // Received: 3 // Received: 4

āϤ⧁āϞāύāĻžāĻŽā§‚āϞāĻ• āϏāĻžāϰāĻŖāĻŋ (Comparison Table)

āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝUnbuffered ChannelBuffered Channel
Capacity0 (āϕ⧋āύ⧋ buffer āύ⧇āχ)āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻ‚āĻ–ā§āϝāĻž (āϝ⧇āĻŽāύ: 5, 10)
Declarationmake(chan int)make(chan int, 5)
Send OperationāϏāĻŦāϏāĻŽāϝāĻŧ block āĻ•āϰ⧇ āϝāϤāĻ•ā§āώāĻŖ āύāĻž receive āĻšāϝāĻŧBuffer full āύāĻž āĻšāϞ⧇ block āĻ•āϰ⧇ āύāĻž
Receive OperationāϏāĻŦāϏāĻŽāϝāĻŧ block āĻ•āϰ⧇ āϝāϤāĻ•ā§āώāĻŖ āύāĻž send āĻšāϝāĻŧBuffer empty āύāĻž āĻšāϞ⧇ block āĻ•āϰ⧇ āύāĻž
SynchronizationPerfect sync (Handshake)Loose coupling
PerformanceSlower (blocking)Faster (non-blocking until full)
Use CaseRequest-Response, Lock-step executionJob Queue, Rate Limiting, Burst handling
Deadlock RiskāĻŦ⧇āĻļāĻŋ (āϝāĻĻāĻŋ receiver āύāĻž āĻĨāĻžāϕ⧇)āĻ•āĻŽ (buffer-āĻ āϜāĻŽāĻž āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇)
Memory UsageāĻ•āĻŽāĻŦ⧇āĻļāĻŋ (buffer size āĻ…āύ⧁āϝāĻžāϝāĻŧā§€)

āĻŦāĻžāĻ¸ā§āϤāĻŦ āĻŦā§āϝāĻŦāĻšāĻžāϰ (Real-world Examples)

Unbuffered Channel āĻŦā§āϝāĻŦāĻšāĻžāϰ:

  • Database transaction-āĻāϰ āĻĒāϰ confirmation
  • API request-response pattern
  • Critical data processing āϝ⧇āĻ–āĻžāύ⧇ acknowledgment āϜāϰ⧁āϰāĻŋ

Buffered Channel āĻŦā§āϝāĻŦāĻšāĻžāϰ:

  • Log processing system (burst of logs)
  • Worker pool pattern
  • Rate limiting APIs
  • Event broadcasting

⧍. Channel āĻĄāĻŋāĻ•ā§āϞāĻžāϰ⧇āĻļāύ āĻ“ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ

// 1. Unbuffered Channel ch := make(chan int) // 2. Buffered Channel (Capacity 5) bufCh := make(chan string, 5) // 3. Nil Channel (Zero Value) var nilCh chan int // āĻāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āϏāĻŦāϏāĻŽāϝāĻŧ block āĻ•āϰ⧇ (Select-āĻ āĻ•āĻžāĻœā§‡ āϞāĻžāϗ⧇)

ā§Š. Unidirectional Channels (āĻāĻ•āĻŽā§āĻ–ā§€ āĻšā§āϝāĻžāύ⧇āϞ)

āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āϕ⧋āĻĄā§‡ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻšā§āϝāĻžāύ⧇āϞ āĻĒāĻžāĻ āĻžāύ⧋āϰ āϏāĻŽā§Ÿ āφāĻŽāϰāĻž Type Safety-āϰ āϜāĻ¨ā§āϝ āĻĻāĻŋāĻ• āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āϰ⧇ āĻĻāĻŋāχāĨ¤ āĻāϤ⧇ āϭ⧁āϞ āĻ•āϰ⧇ Sender āĻĨ⧇āϕ⧇ āϰāĻŋāĻĄ āĻŦāĻž Receiver-āĻ āϰāĻžāχāϟ āĻ•āϰāĻž āϝāĻžā§Ÿ āύāĻžāĨ¤

āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ:

  • chan<- Type : Send Only (āĻļ⧁āϧ⧁ āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāύ⧋ āϝāĻžāĻŦ⧇)
  • <-chan Type : Receive Only (āĻļ⧁āϧ⧁ āĻĄā§‡āϟāĻž āϰāĻŋāϏāĻŋāĻ­ āĻ•āϰāĻž āϝāĻžāĻŦ⧇)

āϤ⧁āϞāύāĻžāĻŽā§‚āϞāĻ• āϏāĻžāϰāĻŖāĻŋ (Unidirectional Channels)

āϧāϰāĻŖāϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏOperationCompile Error
Bidirectionalchan intSend & Receive āωāĻ­āϝāĻŧāχāϕ⧋āύ⧋ restriction āύ⧇āχ
Send Onlychan<- intāĻļ⧁āϧ⧁ Send (ch <- value)Receive āĻ•āϰāϞ⧇ error
Receive Only<-chan intāĻļ⧁āϧ⧁ Receive (value := <-ch)Send āĻ•āϰāϞ⧇ error

āωāĻĻāĻžāĻšāϰāĻŖ ā§§: Basic Producer-Consumer

package main import "fmt" // āĻāχ āĻĢāĻžāĻ‚āĻļāύ āĻļ⧁āϧ⧁ āĻšā§āϝāĻžāύ⧇āϞ⧇ āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ (Write Only) func producer(out chan<- int) { for i := 0; i < 5; i++ { out <- i } close(out) // Sender āϏāĻŦāϏāĻŽāϝāĻŧ āĻšā§āϝāĻžāύ⧇āϞ āĻ•ā§āϞ⧋āϜ āĻ•āϰ⧇ } // āĻāχ āĻĢāĻžāĻ‚āĻļāύ āĻļ⧁āϧ⧁ āĻšā§āϝāĻžāύ⧇āϞ āĻĨ⧇āϕ⧇ āĻĄā§‡āϟāĻž āĻĒāĻĄāĻŧāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ (Read Only) func consumer(in <-chan int) { for v := range in { fmt.Println("Received:", v) } } func main() { ch := make(chan int) go producer(ch) // bidirectional channel āĻ•āĻžāĻ¸ā§āϟ āĻšāϝāĻŧ⧇ unidirectional āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧ consumer(ch) } // Output: // Received: 0 // Received: 1 // Received: 2 // Received: 3 // Received: 4

āωāĻĻāĻžāĻšāϰāĻŖ ⧍: Compile-Time Type Safety

package main import "fmt" func sendOnly(ch chan<- string) { ch <- "Hello" // val := <-ch // ❌ Compile Error: cannot receive from send-only channel } func receiveOnly(ch <-chan string) { msg := <-ch fmt.Println(msg) // ch <- "World" // ❌ Compile Error: cannot send to receive-only channel } func main() { ch := make(chan string, 1) sendOnly(ch) receiveOnly(ch) } // Output: // Hello

āωāĻĻāĻžāĻšāϰāĻŖ ā§Š: Real-world Pipeline Pattern

package main import "fmt" // Stage 1: Generate numbers func generate(out chan<- int) { for i := 1; i <= 5; i++ { out <- i } close(out) } // Stage 2: Square the numbers func square(in <-chan int, out chan<- int) { for num := range in { out <- num * num } close(out) } // Stage 3: Print results func print(in <-chan int) { for result := range in { fmt.Println("Result:", result) } } func main() { // Pipeline: generate → square → print ch1 := make(chan int) ch2 := make(chan int) go generate(ch1) go square(ch1, ch2) print(ch2) } // Output: // Result: 1 // Result: 4 // Result: 9 // Result: 16 // Result: 25

āϕ⧇āύ Unidirectional Channel āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ?

āϏ⧁āĻŦāĻŋāϧāĻžāĻŦāĻ°ā§āĻŖāύāĻž
Type SafetyCompile-time error āĻĒāĻžāĻŦ⧇āύ āϝāĻĻāĻŋ āϭ⧁āϞ operation āĻ•āϰ⧇āύ
Clear IntentCode āĻĒāĻĄāĻŧāϞ⧇āχ āĻŦā§‹āĻāĻž āϝāĻžāϝāĻŧ āϕ⧇ send āĻ•āϰāĻŦ⧇, āϕ⧇ receive āĻ•āϰāĻŦ⧇
Prevent Bugsāϭ⧁āϞ āĻ•āϰ⧇ close āĻ•āϰāĻž āĻŦāĻž duplicate send/receive āĻāĻĄāĻŧāĻžāύ⧋ āϝāĻžāϝāĻŧ
Better DesignSingle Responsibility Principle follow āĻ•āϰ⧇

Best Practices:

  1. āϏāĻŦāϏāĻŽāϝāĻŧ Producer function-āĻ chan<- āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ (send-only)
  2. āϏāĻŦāϏāĻŽāϝāĻŧ Consumer function-āĻ <-chan āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ (receive-only)
  3. āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ Sender-āχ channel close āĻ•āϰāĻŦ⧇ đŸ”Ĩ, receiver āĻ•āĻ–āύ⧋ āύāϝāĻŧ
  4. Main/Orchestrator function-āĻ bidirectional channel āϰāĻžāϖ⧁āύ, āϤāĻžāϰāĻĒāϰ pass āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ cast āĻšāϝāĻŧ⧇ āϝāĻžāĻŦ⧇

ā§Ē. Channel āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž (Closing) āĻāĻŦāĻ‚ Safety

āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž āϕ⧇āύ āĻĻāϰāĻ•āĻžāϰ?

â™Ļī¸ āĻŦā§‹āĻāĻžāϤ⧇ āϝ⧇ āφāϰ āĻĄā§‡āϟāĻž āφāϏāĻŦ⧇ āύāĻžāĨ¤

āĻ—ā§‹āĻ˛ā§āĻĄā§‡āύ āϰ⧁āϞāϏ (Golden Rules of Closing):

  1. āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ Sender āĻšā§āϝāĻžāύ⧇āϞ āĻ•ā§āϞ⧋āϜ āĻ•āϰāĻŦ⧇āĨ¤ Receiver āĻ•āĻ–āύ⧋ āĻšā§āϝāĻžāύ⧇āϞ āĻ•ā§āϞ⧋āϜ āĻ•āϰāĻŦ⧇ āύāĻžāĨ¤
  2. āĻ•ā§āϞ⧋āϜāĻĄ āĻšā§āϝāĻžāύ⧇āϞ⧇ Send āĻ•āϰāϞ⧇ panic āĻšāĻŦ⧇āĨ¤
  3. đŸ”ĨāĻ•ā§āϞ⧋āϜāĻĄ āĻšā§āϝāĻžāύ⧇āϞ āĻĨ⧇āϕ⧇ Receive āĻ•āϰāϞ⧇ āϏ⧇āϟāĻŋ āφāϰ āĻŦā§āϞāĻ• āĻšāĻŦ⧇ āύāĻž, āĻŦāϰāĻ‚ āϏ⧇āχ āϟāĻžāχāĻĒ⧇āϰ Zero Value āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰāĻŦ⧇āĨ¤đŸ”Ĩ
close(ch)

Close āĻ•āϰāĻž āĻŽāĻžāύ⧇:

  • āφāϰ send āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻž (send āĻ•āϰāϞ⧇ panic)
  • āĻ•āĻŋāĻ¨ā§āϤ⧁ receive āĻ•āϰāĻž āϝāĻžāĻŦ⧇ (zero-value + ok flag)

āύāĻŋāϰāĻžāĻĒāĻĻ⧇ āϰāĻŋāĻĄ āĻ•āϰāĻžāϰ āĻĒāĻĻā§āϧāϤāĻŋ (val, ok idiom):

v, ok := <-ch if !ok { fmt.Println("Channel is closed and empty!") return } fmt.Println("Value:", v)

Channel-āĻāϰ āĻ“āĻĒāϰ loop āĻ•āϰāĻž (for-range):

for v := range ch { fmt.Println(v) }

range channel close āĻšāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϚāϞāĻŦ⧇āĨ¤

Channel-āĻāϰ āφāĻ•āĻžāϰ āĻĻ⧇āĻ–āĻž

len(ch) // buffer āĻ āĻ•ā§ŸāϟāĻž item āφāϛ⧇ cap(ch) // buffer capacity

āωāĻĒāĻ•āĻžāϰ⧀ debugging āĻāĨ¤

10 āϏāĻ‚āĻ–ā§āϝāĻž āĻĒāĻžāĻ āĻžāĻ“ āĻāĻŦāĻ‚ āĻĒā§āϰāĻŋāĻ¨ā§āϟ āĻ•āϰ⧋

package main import "fmt" func main() { ch := make(chan int) go func() { for i := 1; i <= 10; i++ { ch <- i } close(ch) }() for v := range ch { fmt.Println(v) } }

ā§Ģ. Nil Channel-āĻāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ

nil āĻšā§āϝāĻžāύ⧇āϞ āϰāĻŋāĻĄ āĻŦāĻž āϰāĻžāχāϟ āĻ•āϰāϞ⧇ āĻ—ā§‹āϰ⧁āϟāĻŋāύ āĻ¸ā§āĻĨāĻžāϝāĻŧā§€āĻ­āĻžāĻŦ⧇ āĻŦā§āϞāĻ• āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤ āĻāϟāĻž āĻļ⧁āύāϤ⧇ āĻ–āĻžāϰāĻžāĻĒ āϞāĻžāĻ—āϞ⧇āĻ“ select āĻ¸ā§āĻŸā§‡āϟāĻŽā§‡āĻ¨ā§āĻŸā§‡ āϕ⧋āύ⧋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ case āϕ⧇ āϏāĻžāĻŽāϝāĻŧāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ (disable) āĻ•āϰāϤ⧇ āĻāϟāĻŋ āϖ⧁āĻŦ āĻ•āĻžāĻœā§‡āϰāĨ¤

// āϧāϰ⧁āύ ch1 āĻ•ā§āϞ⧋āϜ āĻšā§Ÿā§‡ āϗ⧇āϛ⧇, āφāĻŽāϰāĻž āϚāĻžāχ āύāĻž ch1 āĻĨ⧇āϕ⧇ āφāϰ āϰāĻŋāĻĄ āĻšā§‹āĻ• select { case v, ok := <-ch1: if !ok { ch1 = nil // ch1 āĻāĻ–āύ nil, āĻāχ case āφāϰ āĻ•āĻ–āύ⧋ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟ āĻšāĻŦ⧇ āύāĻž } else { fmt.Println(v) } case v := <-ch2: fmt.Println(v) }

ā§Ŧ. Production Patterns (āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύāϏ)

āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ ā§§: Worker Pool (āĻ•āύāĻ•āĻžāϰ⧇āĻ¨ā§āϏāĻŋ āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞ)

āĻāĻ•āϏāĻžāĻĨ⧇ āĻšāĻžāϜāĻžāϰ āĻšāĻžāϜāĻžāϰ āĻ—ā§‹āϰ⧁āϟāĻŋāύ āύāĻž āϚāĻžāϞāĻŋā§Ÿā§‡ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻ‚āĻ–ā§āϝāĻ• (āϝ⧇āĻŽāύ ā§ĢāϟāĻŋ) āĻ—ā§‹āϰ⧁āϟāĻŋāύ āĻĻāĻŋā§Ÿā§‡ āĻ•āĻžāϜ āĻ•āϰāĻžāύ⧋āĨ¤

func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("Worker", id, "started job", j) time.Sleep(time.Second) // āĻ­āĻžāϰ⧀ āĻ•āĻžāϜ āϏāĻŋāĻŽā§āϞ⧇āĻļāύ results <- j * 2 } } func main() { jobs := make(chan int, 100) results := make(chan int, 100) // ā§ŠāϟāĻŋ Worker āϚāĻžāϞ⧁ āĻ•āϰāϞāĻžāĻŽ for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // ā§ĢāϟāĻŋ āĻ•āĻžāϜ āĻĒāĻžāĻ āĻžāϞāĻžāĻŽ for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // āĻ•āĻžāϜ āĻĒāĻžāĻ āĻžāύ⧋ āĻļ⧇āώ // āϰ⧇āϜāĻžāĻ˛ā§āϟ āϏāĻ‚āĻ—ā§āϰāĻš for a := 1; a <= 5; a++ { <-results } }

āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ ⧍: Graceful Shutdown (Done Channel)

āϕ⧋āύ⧋ āĻĒā§āϰāϏ⧇āϏāϕ⧇ āĻŽāĻžāĻāĻĒāĻĨ⧇ āĻĨāĻžāĻŽāĻžāύ⧋āϰ āϜāĻ¨ā§āϝāĨ¤

func doWork(done <-chan bool) { for { select { case <-done: fmt.Println("Stopping work...") return default: fmt.Println("Working...") time.Sleep(500 * time.Millisecond) } } } func main() { done := make(chan bool) go doWork(done) time.Sleep(2 * time.Second) close(done) // āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ āĻĒāĻžāĻ āĻžāύ⧋ āĻšāϞ⧋ āĻĨāĻžāĻŽāĻžāϰ āϜāĻ¨ā§āϝ time.Sleep(1 * time.Second) }

ā§Ž. Common Pitfalls (āϏāĻžāϧāĻžāϰāĻŖ āϭ⧁āϞ āĻ“ āϏāĻŽāĻžāϧāĻžāύ)

āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāĻĢāϞāĻžāĻĢāϞāϏāĻŽāĻžāϧāĻžāύ
Send on Closed ChannelPanicāύāĻŋāĻļā§āϚāĻŋāϤ āĻšā§‹āύ āĻšā§āϝāĻžāύ⧇āϞ āĻ•ā§āϞ⧋āϜ āĻ•āϰāĻžāϰ āĻĒāϰ āϕ⧇āω āϝ⧇āύ āφāϰ āϰāĻžāχāϟ āύāĻž āĻ•āϰ⧇āĨ¤ sync.Once āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āĻ•ā§āϞ⧋āϜāĻŋāĻ‚ā§Ÿā§‡āϰ āϜāĻ¨ā§āϝāĨ¤
Close on Closed ChannelPanicāĻšā§āϝāĻžāύ⧇āϞ āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āĻŦāĻžāϰāχ āĻ•ā§āϞ⧋āϜ āĻ•āϰāϤ⧇ āĻšā§ŸāĨ¤
Receive from Nil ChannelBlock Forevernil āĻšā§āϝāĻžāύ⧇āϞ āϏāĻžāĻŦāϧāĻžāύ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤
Send to Nil ChannelBlock ForeverāĻšā§āϝāĻžāύ⧇āϞ āχāύāĻŋāĻļāĻŋāϝāĻŧāĻžāϞāĻžāχāϜ (make) āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇ āĻ•āĻŋ āύāĻž āĻšā§‡āĻ• āĻ•āϰ⧁āύāĨ¤
Unbuffered Channel with no receiverDeadlockāύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āĻ…āĻ¨ā§āϝ āĻ—ā§‹āϰ⧁āϟāĻŋāύ āϰ⧇āĻĄāĻŋ āφāϛ⧇ āĻ…āĻĨāĻŦāĻž Buffered Channel āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤

āϭ⧁āϞāĻĢāϞāĻžāĻĢāϞāϕ⧇āύ
Receive āφāϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ Send āύ⧇āχDeadlockāϕ⧇āω data āĻĒāĻžāĻ āĻžāĻšā§āϛ⧇ āύāĻž
Send āφāϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ Receive āύ⧇āχDeadlockchannel overflow (unbuffered)
Buffered full, but no receiverDeadlockbuffer āĻĒā§‚āĻ°ā§āĻŖ āĻšā§Ÿā§‡ āϗ⧇āϛ⧇
Close āĻ•āϰāĻžāϰ āĻĒāϰ sendPanicāĻŦāĻ¨ā§āϧ channel-āĻ āϞ⧇āĻ–āĻž āϝāĻžā§Ÿ āύāĻž
Close āύāĻž āĻ•āϰ⧇ range āĻ•āϰāϞ⧇Infinite waitāĻ•āĻ–āύ⧋ close āϧāϰāĻŦ⧇ āύāĻž

📝 āĻāĻ•āύāϜāϰ⧇ āĻŽāύ⧇ āϰāĻžāĻ–āĻžāϰ āĻŽāϤ⧋ (Cheat Sheet)

  1. āχāύāĻŋāĻļāĻŋāϝāĻŧāĻžāϞāĻžāχāĻœā§‡āĻļāύ: make(chan type) āĻ›āĻžā§œāĻž āĻšā§āϝāĻžāύ⧇āϞ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āϏ⧇āϟāĻŋ nil āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āĻ•āĻžāϜ āĻ•āϰ⧇ āύāĻžāĨ¤
  2. āĻŽāĻžāϞāĻŋāĻ•āĻžāύāĻž (Ownership): āϝ⧇ āĻ—ā§‹āϰ⧁āϟāĻŋāύ āĻšā§āϝāĻžāύ⧇āϞ⧇ āĻĄā§‡āϟāĻž āĻĒāĻžāĻ āĻžāϝāĻŧ (Send), āϏ⧇āχ āĻ—ā§‹āϰ⧁āϟāĻŋāύ-āχ āĻšā§āϝāĻžāύ⧇āϞāϟāĻŋ close āĻ•āϰāĻŦ⧇āĨ¤
  3. āϞ⧁āĻĒ: for range āϞ⧁āĻĒ āĻšā§āϝāĻžāύ⧇āϞ āĻ•ā§āϞ⧋āϜ āύāĻž āĻšāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϚāϞāϤ⧇āχ āĻĨāĻžāϕ⧇āĨ¤ āϤāĻžāχ Sender-āϕ⧇ āĻ…āĻŦāĻļā§āϝāχ āĻ•āĻžāϜ āĻļ⧇āώ⧇ close() āĻ•āϞ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇, āύāϤ⧁āĻŦāĻž Receiver deadlock āĻ–āĻžāĻŦ⧇āĨ¤
  4. āĻŦāĻžāĻĢāĻžāϰ: āĻŦāĻžāĻĢāĻžāϰāĻĄ āĻšā§āϝāĻžāύ⧇āϞ āĻĒā§‚āĻ°ā§āĻŖ āύāĻž āĻšāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻŦā§āϞāĻ• āĻšā§Ÿ āύāĻžāĨ¤ āĻĒāĻžāϰāĻĢāϰāĻŽā§āϝāĻžāĻ¨ā§āϏ āĻŦāĻžā§œāĻžāϤ⧇ āϏāĻ āĻŋāĻ• āϏāĻžāχāĻœā§‡āϰ āĻŦāĻžāĻĢāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤
  5. Select: āĻŽāĻžāĻ˛ā§āϟāĻŋāĻĒāϞ āĻšā§āϝāĻžāύ⧇āϞ āĻšā§āϝāĻžāĻ¨ā§āĻĄāϞāĻŋāĻ‚ āĻāĻŦāĻ‚ āϟāĻžāχāĻŽāφāωāϟ āϞāϜāĻŋāϕ⧇āϰ āϜāĻ¨ā§āϝ select āĻšāϞ⧋ āϏ⧇āϰāĻž āωāĻĒāĻžā§ŸāĨ¤