Select Statement
select memungkinkan goroutine menunggu di beberapa channel sekaligus. Mirip switch, tapi untuk channel operations.
Sintaks Dasar
select {
case msg := <-ch1:
fmt.Println("Dari ch1:", msg)
case msg := <-ch2:
fmt.Println("Dari ch2:", msg)
case ch3 <- "hello":
fmt.Println("Terkirim ke ch3")
default:
fmt.Println("Tidak ada channel yang ready")
}
Timeout Pattern
select {
case result := <-ch:
fmt.Println("Hasil:", result)
case <-time.After(3 * time.Second):
fmt.Println("Timeout!")
}
Done Channel Pattern
Menggunakan channel untuk memberi sinyal berhenti ke goroutine:
func worker(done chan bool) {
for {
select {
case <-done:
fmt.Println("Worker berhenti")
return
default:
fmt.Println("Bekerja...")
time.Sleep(500 * time.Millisecond)
}
}
}
func main() {
done := make(chan bool)
go worker(done)
time.Sleep(2 * time.Second)
done <- true // Kirim sinyal berhenti
}
Context (Modern Approach)
Package context adalah cara modern untuk mengontrol goroutine:
import "context"
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Worker dibatalkan:", ctx.Err())
return
default:
fmt.Println("Bekerja...")
time.Sleep(500 * time.Millisecond)
}
}
}
func main() {
ctx, cancel := context.WithTimeout(
context.Background(),
2*time.Second,
)
defer cancel()
go worker(ctx)
time.Sleep(3 * time.Second)
}
Common Patterns
- Pipeline — Chain goroutine: satu menghasilkan, yang lain memproses
- Fan-Out/Fan-In — Distribusi pekerjaan ke banyak goroutine, kumpulkan hasilnya
- Worker Pool — Sejumlah tetap goroutine memproses job dari channel
- Rate Limiting — Gunakan
time.Tickuntuk membatasi throughput
Worker Pool Example
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d memproses job %d\n", id, j)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Buat 3 worker
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Kirim 5 job
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Kumpulkan hasil
for a := 1; a <= 5; a++ {
fmt.Println(<-results)
}
}