Channel - Select
Tunggu beberapa channel sekaligus dan tanggapilah yang pertama siap.
Pahami konsepnya
select seperti switch untuk channel: ia menunggu SEMUA case-nya dan menjalankan satu yang channel-nya pertama siap — baik pengiriman maupun penerimaan. Bila beberapa siap bersamaan, Go memilih secara acak agar adil.
Case dengan default bersifat non-blok: bila tak ada channel yang siap, cabang default langsung jalan. Ini berguna untuk polling — mencoba mengambil data bila ada, lanjut bila tidak — atau mengirim bila consumer tersedia.
select adalah bahan dasar pola penting: timeout (pelajaran berikutnya), membatalkan pekerjaan, dan multiplexing — satu goroutine melayani banyak sumber. Tanpa select, menunggu dua channel berarti dua penerimaan berurutan yang saling mengunci.
Coba contoh kode
package main
import (
"fmt"
"time"
)
func main() {
cepat := make(chan string)
lambat := make(chan string)
go func() {
time.Sleep(1 * time.Second)
cepat <- "satu detik"
}()
go func() {
time.Sleep(3 * time.Second)
lambat <- "tiga detik"
}()
for i := 0; i < 2; i++ {
select {
case pesan := <-cepat:
fmt.Println("dari cepat:", pesan)
case pesan := <-lambat:
fmt.Println("dari lambat:", pesan)
}
}
}Loop dua kali karena ada dua pesan yang datang. Pada putaran pertama select, channel cepat siap lebih dulu sehingga cabangnya jalan; putaran kedua menunggu lambat. Tanpa select, menerima cepat dulu baru lambat tetap bisa — tetapi select-lah yang memungkinkan bereaksi terhadap sumber mana pun yang lebih dulu siap.
default: polling tanpa mengunci
func main() {
ch := make(chan int)
select {
case n := <-ch:
fmt.Println("dapat", n)
default:
fmt.Println("belum ada data, lanjut kerja lain")
}
}Channel kosong tanpa penerima-pengirim lain membuat select langsung melompat ke default — program tidak pernah terkunci. Pola ini dipakai untuk loop event: periksa data, proses bila ada, lakukan hal lain bila tidak.
Latihan singkat
Uji: terima dua sumber (1 detik & 3 detik) memakai select — harus mencetak `satu detik` lalu `tiga detik`.