Channel - Timeout
Batasi lama menunggu dengan time.After dan select.
Pahami konsepnya
Menunggu tanpa batas itu berbahaya: goroutine lawan bisa macet, jaringan bisa menggantung, dan programmu ikut beku. Go menjawabnya dengan kombinasi select dan time.After(durasi) — channel yang mengirim satu nilai tepat setelah durasi tersebut berlalu.
Diletakkan sebagai salah satu case select, time.After menjadi alarm: bila data tiba lebih dulu, cabang data yang jalan dan alarm diabaikan; bila batas waktu tercapai duluan, cabang timeout jalan dan kamu bebas memutuskan — kembalikan error, coba ulang, atau tinggalkan.
Timeout adalah pola wajib untuk panggilan jaringan dan pekerjaan yang tidak boleh menggantung. Prinsipnya: setiap channel yang kamu tunggu layak punya rencana B — berapa lama kamu sanggup menunggu, dan apa yang dilakukan setelahnya.
Coba contoh kode
package main
import (
"errors"
"fmt"
"time"
)
func ambilLambat(ch chan string) {
time.Sleep(3 * time.Second) // simulasi layanan lambat
ch <- "data"
}
func main() {
ch := make(chan string)
go ambilLambat(ch)
select {
case data := <-ch:
fmt.Println("dapat:", data)
case <-time.After(1 * time.Second):
fmt.Println("timeout: terlalu lama menunggu")
}
}Layanan simulasi butuh tiga detik, tetapi alarm dipasang satu detik — cabang timeout menang dan program keluar setelah satu detik, tidak ikut menggantung tiga detik. Ubah durasi time.After menjadi 5 detik dan cabang data yang akan menang.
Timeout yang mengembalikan error
func ambil(ch chan string) (string, error) {
select {
case v := <-ch:
return v, nil
case <-time.After(2 * time.Second):
return "", errors.New("batas waktu terlampaui")
}
}
func main() {
ch := make(chan string)
go func() { time.Sleep(3 * time.Second); ch <- "telat" }()
if _, err := ambil(ch); err != nil {
fmt.Println("gagal:", err)
}
}Membungkus select dalam fungsi bernilai (string, error) membuat timeout menjadi bagian normal alur error — pemanggil menanganinya dengan if err != nil seperti kegagalan lain. Inilah bentuk timeout dalam produksi.
Latihan singkat
Uji: layanan lambat 2 detik versus alarm 500ms — program harus mencetak persis `timeout: terlalu lama` (lalu berhenti, tidak menunggu 2 detik).