← Kembali ke kursus
Pelajaran kursus · Go
Pelajaran 30

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).