Channel & Select
Komunikasi antar goroutine dengan channel, close, range, dan select.
Jangan berbagi memori, saling berkomunikasi
Filosofi Go: "Don't communicate by sharing memory; share memory by communicating." Alih-alih beberapa goroutine membaca-menulis variable yang sama, mereka saling mengirim data lewat channel.
Membuat dan memakai channel
ch := make(chan int) // channel untuk int
go func() {
ch <- 42 // kirim
}()
v := <-ch // terima (menunggu sampai ada)
fmt.Println(v) // 42
Pada channel tanpa buffer, pengirim dan penerima harus bertemu bersamaan; salah satu akan menunggu yang lain.
Channel dengan buffer
ch := make(chan int, 2) // kapasitas 2
ch <- 1
ch <- 2 // belum memblokir
// ch <- 3 akan memblokir sampai ada yang menerima
close dan range
Pengirim menutup channel bila tidak ada data lagi. Penerima bisa menelusurinya dengan range sampai channel tertutup:
go func() {
for i := 1; i <= 5; i++ {
ch <- i
}
close(ch)
}()
for v := range ch {
fmt.Println(v)
}
Aturan: hanya pengirim yang menutup channel. Mengirim ke channel yang sudah ditutup menyebabkan panic.
Arah channel
Di parameter function, batasi arahnya agar lebih aman:
func produsen(out chan<- int) { ... } // hanya boleh mengirim
func konsumen(in <-chan int) { ... } // hanya boleh menerima
select
Menunggu beberapa operasi channel sekaligus dan menjalankan yang pertama siap:
select {
case v := <-ch1:
fmt.Println("dari ch1", v)
case v := <-ch2:
fmt.Println("dari ch2", v)
case <-time.After(2 * time.Second):
fmt.Println("timeout")
default:
fmt.Println("tidak ada yang siap")
}
Deadlock
Jika semua goroutine saling menunggu, Go mendeteksinya dan program berhenti dengan fatal error: all goroutines are asleep - deadlock!. Penyebab umum: menerima dari channel yang tak pernah dikirimi, atau lupa close pada range.
Pola worker pool
Beberapa goroutine membaca tugas dari satu channel dan menulis hasil ke channel lain — pola dasar untuk memproses banyak pekerjaan secara paralel.