Lompati ke konten utama
Modul 7 · Pelajaran 5 dari 535/50 dalam kursus~14 min
Pelajaran modul (5/5)

`context.Context`: pembatalan dan tenggat waktu

Paket context adalah standar de-facto untuk propagasi pembatalan, tenggat waktu, dan nilai yang terikat cakupan di sepanjang rantai panggilan, di beberapa goroutine. Semua paket "jaringan" standar (net/http, database/sql, os/exec) menerima context.Context sebagai parameter pertama mereka.

Antarmuka

Go
type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key any) any
}
  • Done(): saluran yang ditutup ketika konteksnya dibatalkan.
  • Err(): alasan pembatalan (context.Canceled atau context.DeadlineExceeded).
  • Deadline(): batas waktu opsional.
  • Value(): pencarian nilai yang terikat cakupan (gunakan dengan hemat).

Empat fungsi dasar

Go
ctx := context.Background()              // radice: usalo in main, init, test
ctx := context.TODO()                    // "non so ancora": stub esplicito

ctx, cancel := context.WithCancel(parent)               // cancel manuale
ctx, cancel := context.WithTimeout(parent, d)           // scadenza relativa
ctx, cancel := context.WithDeadline(parent, t)          // scadenza assoluta

ctx := context.WithValue(parent, key, value)            // valore scope-bound

Semua formulir turunan mengembalikan fungsi cancel: selalu panggil saja (idealnya dengan defer) untuk melepaskan sumber daya internal, meskipun konteksnya sudah habis masa berlakunya.

Pola batas waktu

Go
func fetchUser(id string) (*User, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    return queryUser(ctx, id)   // queryUser deve rispettare ctx
}

Jika queryUser membutuhkan waktu lebih dari 2 detik, ctx.Done() ditutup dan fungsi tersebut harus membatalkan operasi.

Menghargai konteks: pilih pada Selesai()

Go
func slowWork(ctx context.Context) error {
    for {
        select {
        case <-ctx.Done():
            return ctx.Err()      // canceled o deadline exceeded
        case <-time.After(100 * time.Millisecond):
            // un tick di lavoro
        }
    }
}

Aturannya: di mana pun fungsi Anda mungkin diblokir untuk waktu yang lama, itu akan terjadi harus menangani ctx.Selesai(). Kalau tidak, konteksnya adalah "dinyalakan" untuk tidak ada apa-apa.

Konvensi parameter pertama

Go
func Fetch(ctx context.Context, url string) ([]byte, error) { ... }
//        ^^^^^^^^^^^^^^^^^^^
// SEMPRE primo, mai dentro a una struct, mai opzionale
  • ctx SELALU sebagai parameter pertama, bernama ctx.
  • Jangan pernah memasukkan Context sebagai bidang struct (pengecualian yang sangat jarang terjadi).
  • Jangan pernah melewati nil: gunakan context.TODO() sebagai stub.

konteks.WithValue: hemat

Go
type userKey struct{}

ctx := context.WithValue(ctx, userKey{}, currentUser)
// più sotto:
if u, ok := ctx.Value(userKey{}).(*User); ok { ... }

Pedoman:

  • HANYA untuk data cakupan permintaan (ID permintaan, ID jejak, identitas pengguna).
  • JANGAN PERNAH untuk parameter fungsi: teruskan secara normal.
  • Kunci jenis kustom yang tidak diekspor untuk menghindari tabrakan.

Propagasi sepanjang rantai

Go
func handleHTTP(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()   // context legato al ciclo di vita della richiesta
    user, err := fetchUser(ctx, r.URL.Query().Get("id"))
    if err != nil { ... }
    // ...
}

net/http secara otomatis membatalkan r.Context() saat klien terputus atau ketika pawang kembali. Dengan menyebarkannya ke semua orang panggilan hilir, seluruh pohon operasi dibatalkan cascade: tidak ada pekerjaan yang sia-sia setelah terputus.

Cobalah

Latihan#go.m7.l5.e1
Upaya: 0Memuat…

Buat konteks dengan batas waktu 1 detik yang berasal dari konteks.Background() dan ingatlah untuk memanggil pembatalan dengan penundaan.

Memuat editor…
Tunjukkan petunjuk

`context.WithTimeout(parent, d)` mengembalikan `(ctx, cancel)`; selalu menelepon batal.

Solusi tersedia setelah 3 upaya

Latihan#go.m7.l5.e2
Upaya: 0Memuat…

Gunakan <-ctx.Done() dalam pilihan untuk menunggu konteks dibatalkan.

Memuat editor…
Tunjukkan petunjuk

`ctx.Done()` adalah saluran yang ditutup ketika konteksnya dibatalkan.

Solusi tersedia setelah 3 upaya

Quiz#go.m7.l5.e3
Siap

Berdasarkan konvensi, kemana perginya parameter ctx dalam tanda tangan fungsi?

Go
func Fetch(???, url string) ([]byte, error)
Pilihan jawaban

Rekap

  • context.Context menyebarkan nilai pembatalan, tenggat waktu, dan terikat cakupan.
  • Background()/TODO() sebagai akar; WithCancel/WithTimeout/WithDeadline untuk memperoleh.
  • Selalu defer cancel() untuk melepaskan sumber daya.
  • Fungsi "Panjang" harus select di ctx.Done() atau meneruskan ctx ke paket standar.
  • Konvensi: ctx sebagai parameter PERTAMA, tidak pernah berada di dalam struct.
  • WithValue hanya untuk data cakupan permintaan (ID permintaan, ID pelacakan).
  • Di net/http, r.Context() dibatalkan saat klien terputus.