đ 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 Channel | Buffered Channel |
|---|---|---|
| Capacity | 0 (āĻā§āύ⧠buffer āύā§āĻ) | āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āϏāĻāĻā§āϝāĻž (āϝā§āĻŽāύ: 5, 10) |
| Declaration | make(chan int) | make(chan int, 5) |
| Send Operation | āϏāĻŦāϏāĻŽāϝāĻŧ block āĻāϰ⧠āϝāϤāĻā§āώāĻŖ āύāĻž receive āĻšāϝāĻŧ | Buffer full āύāĻž āĻšāϞ⧠block āĻāϰ⧠āύāĻž |
| Receive Operation | āϏāĻŦāϏāĻŽāϝāĻŧ block āĻāϰ⧠āϝāϤāĻā§āώāĻŖ āύāĻž send āĻšāϝāĻŧ | Buffer empty āύāĻž āĻšāϞ⧠block āĻāϰ⧠āύāĻž |
| Synchronization | Perfect sync (Handshake) | Loose coupling |
| Performance | Slower (blocking) | Faster (non-blocking until full) |
| Use Case | Request-Response, Lock-step execution | Job 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)
| āϧāϰāĻŖ | āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏ | Operation | Compile Error |
|---|---|---|---|
| Bidirectional | chan int | Send & Receive āĻāĻāϝāĻŧāĻ | āĻā§āύ⧠restriction āύā§āĻ |
| Send Only | chan<- 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 Safety | Compile-time error āĻĒāĻžāĻŦā§āύ āϝāĻĻāĻŋ āĻā§āϞ operation āĻāϰā§āύ |
| Clear Intent | Code āĻĒāĻĄāĻŧāϞā§āĻ āĻŦā§āĻāĻž āϝāĻžāϝāĻŧ āĻā§ send āĻāϰāĻŦā§, āĻā§ receive āĻāϰāĻŦā§ |
| Prevent Bugs | āĻā§āϞ āĻāϰ⧠close āĻāϰāĻž āĻŦāĻž duplicate send/receive āĻāĻĄāĻŧāĻžāύ⧠āϝāĻžāϝāĻŧ |
| Better Design | Single Responsibility Principle follow āĻāϰ⧠|
Best Practices:
- āϏāĻŦāϏāĻŽāϝāĻŧ Producer function-āĻ
chan<-āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ (send-only) - āϏāĻŦāϏāĻŽāϝāĻŧ Consumer function-āĻ
<-chanāĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ (receive-only) - āĻļā§āϧā§āĻŽāĻžāϤā§āϰ Sender-āĻ channel close āĻāϰāĻŦā§ đĨ, receiver āĻāĻāύ⧠āύāϝāĻŧ
- Main/Orchestrator function-āĻ bidirectional channel āϰāĻžāĻā§āύ, āϤāĻžāϰāĻĒāϰ pass āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ cast āĻšāϝāĻŧā§ āϝāĻžāĻŦā§
ā§Ē. Channel āĻŦāύā§āϧ āĻāϰāĻž (Closing) āĻāĻŦāĻ Safety
āĻŦāύā§āϧ āĻāϰāĻž āĻā§āύ āĻĻāϰāĻāĻžāϰ?
âĻī¸ āĻŦā§āĻāĻžāϤ⧠āϝ⧠āĻāϰ āĻĄā§āĻāĻž āĻāϏāĻŦā§ āύāĻžāĨ¤
āĻā§āϞā§āĻĄā§āύ āϰā§āϞāϏ (Golden Rules of Closing):
- āĻļā§āϧā§āĻŽāĻžāϤā§āϰ Sender āĻā§āϝāĻžāύā§āϞ āĻā§āϞā§āĻ āĻāϰāĻŦā§āĨ¤ Receiver āĻāĻāύ⧠āĻā§āϝāĻžāύā§āϞ āĻā§āϞā§āĻ āĻāϰāĻŦā§ āύāĻžāĨ¤
- āĻā§āϞā§āĻāĻĄ āĻā§āϝāĻžāύā§āϞ⧠Send āĻāϰāϞā§
panicāĻšāĻŦā§āĨ¤ - đĨāĻā§āϞā§āĻāĻĄ āĻā§āϝāĻžāύā§āϞ āĻĨā§āĻā§ 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 Channel | Panic | āύāĻŋāĻļā§āĻāĻŋāϤ āĻšā§āύ āĻā§āϝāĻžāύā§āϞ āĻā§āϞā§āĻ āĻāϰāĻžāϰ āĻĒāϰ āĻā§āĻ āϝā§āύ āĻāϰ āϰāĻžāĻāĻ āύāĻž āĻāϰā§āĨ¤ sync.Once āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ āĻā§āϞā§āĻāĻŋāĻā§ā§āϰ āĻāύā§āϝāĨ¤ |
| Close on Closed Channel | Panic | āĻā§āϝāĻžāύā§āϞ āĻŽāĻžāϤā§āϰ āĻāĻāĻŦāĻžāϰāĻ āĻā§āϞā§āĻ āĻāϰāϤ⧠āĻšā§āĨ¤ |
| Receive from Nil Channel | Block Forever | nil āĻā§āϝāĻžāύā§āϞ āϏāĻžāĻŦāϧāĻžāύ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤ |
| Send to Nil Channel | Block Forever | āĻā§āϝāĻžāύā§āϞ āĻāύāĻŋāĻļāĻŋāϝāĻŧāĻžāϞāĻžāĻāĻ (make) āĻāϰāĻž āĻšā§ā§āĻā§ āĻāĻŋ āύāĻž āĻā§āĻ āĻāϰā§āύāĨ¤ |
| Unbuffered Channel with no receiver | Deadlock | āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰā§āύ āĻ āύā§āϝ āĻā§āϰā§āĻāĻŋāύ āϰā§āĻĄāĻŋ āĻāĻā§ āĻ āĻĨāĻŦāĻž Buffered Channel āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤ |
| āĻā§āϞ | āĻĢāϞāĻžāĻĢāϞ | āĻā§āύ |
|---|---|---|
| Receive āĻāĻā§ āĻāĻŋāύā§āϤ⧠Send āύā§āĻ | Deadlock | āĻā§āĻ data āĻĒāĻžāĻ āĻžāĻā§āĻā§ āύāĻž |
| Send āĻāĻā§ āĻāĻŋāύā§āϤ⧠Receive āύā§āĻ | Deadlock | channel overflow (unbuffered) |
| Buffered full, but no receiver | Deadlock | buffer āĻĒā§āϰā§āĻŖ āĻšā§ā§ āĻā§āĻā§ |
| Close āĻāϰāĻžāϰ āĻĒāϰ send | Panic | āĻŦāύā§āϧ channel-āĻ āϞā§āĻāĻž āϝāĻžā§ āύāĻž |
| Close āύāĻž āĻāϰ⧠range āĻāϰāϞ⧠| Infinite wait | āĻāĻāύ⧠close āϧāϰāĻŦā§ āύāĻž |
đ āĻāĻāύāĻāϰ⧠āĻŽāύ⧠āϰāĻžāĻāĻžāϰ āĻŽāϤ⧠(Cheat Sheet)
- āĻāύāĻŋāĻļāĻŋāϝāĻŧāĻžāϞāĻžāĻāĻā§āĻļāύ:
make(chan type)āĻāĻžā§āĻž āĻā§āϝāĻžāύā§āϞ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϞ⧠āϏā§āĻāĻŋnilāĻĨāĻžāĻā§ āĻāĻŦāĻ āĻāĻžāĻ āĻāϰ⧠āύāĻžāĨ¤ - āĻŽāĻžāϞāĻŋāĻāĻžāύāĻž (Ownership): āϝ⧠āĻā§āϰā§āĻāĻŋāύ āĻā§āϝāĻžāύā§āϞ⧠āĻĄā§āĻāĻž āĻĒāĻžāĻ āĻžāϝāĻŧ (Send), āϏā§āĻ āĻā§āϰā§āĻāĻŋāύ-āĻ āĻā§āϝāĻžāύā§āϞāĻāĻŋ
closeāĻāϰāĻŦā§āĨ¤ - āϞā§āĻĒ:
for rangeāϞā§āĻĒ āĻā§āϝāĻžāύā§āϞ āĻā§āϞā§āĻ āύāĻž āĻšāĻā§āĻž āĻĒāϰā§āϝāύā§āϤ āĻāϞāϤā§āĻ āĻĨāĻžāĻā§āĨ¤ āϤāĻžāĻ Sender-āĻā§ āĻ āĻŦāĻļā§āϝāĻ āĻāĻžāĻ āĻļā§āώā§close()āĻāϞ āĻāϰāϤ⧠āĻšāĻŦā§, āύāϤā§āĻŦāĻž ReceiverdeadlockāĻāĻžāĻŦā§āĨ¤ - āĻŦāĻžāĻĢāĻžāϰ: āĻŦāĻžāĻĢāĻžāϰāĻĄ āĻā§āϝāĻžāύā§āϞ āĻĒā§āϰā§āĻŖ āύāĻž āĻšāĻā§āĻž āĻĒāϰā§āϝāύā§āϤ āĻŦā§āϞāĻ āĻšā§ āύāĻžāĨ¤ āĻĒāĻžāϰāĻĢāϰāĻŽā§āϝāĻžāύā§āϏ āĻŦāĻžā§āĻžāϤ⧠āϏāĻ āĻŋāĻ āϏāĻžāĻāĻā§āϰ āĻŦāĻžāĻĢāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤
- Select: āĻŽāĻžāϞā§āĻāĻŋāĻĒāϞ āĻā§āϝāĻžāύā§āϞ āĻšā§āϝāĻžāύā§āĻĄāϞāĻŋāĻ āĻāĻŦāĻ āĻāĻžāĻāĻŽāĻāĻāĻ āϞāĻāĻŋāĻā§āϰ āĻāύā§āϝ
selectāĻšāϞ⧠āϏā§āϰāĻž āĻāĻĒāĻžā§āĨ¤