Kembali ke seri

Context dan pembatalan

Propagasi timeout dan sinyal shutdown ke setiap lapisan layanan Go Anda.

Daftar Isi

Goroutine tanpa pembatalan akan bocor. Context adalah jawaban Go: nilai yang Anda oper ke bawah rantai pemanggilan, membawa deadline, sinyal cancel, dan data request-scoped.

Polanya

func handler(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
    defer cancel()

    data, err := fetch(ctx, "https://example.com")
    if err != nil {
        http.Error(w, "upstream timeout", http.StatusGatewayTimeout)
        return
    }
    w.Write(data)
}

func fetch(ctx context.Context, url string) ([]byte, error) {
    req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    return io.ReadAll(resp.Body)
}

Aturan yang menyelamatkan Anda

  1. ctx selalu parameter pertama, dinamai ctx
  2. Panggil cancel() — defer cancel() begitu Anda membuat derived context
  3. Jangan pernah menyimpan context di struct; oper secara eksplisit
  4. Select pada ctx.Done() di dalam loop yang bisa berjalan lama

Dikombinasikan dengan channel ber-buffer dari bagian 1, ini fondasi layanan yang bisa shutdown dengan bersih.