Ana içeriğe geç
Modül 7 · Ders 5 ders 5Kurstaki 35/50~14 min
Modül dersleri (5/5)

`context.Context`: iptal ve son tarihler

context paketi yayılma için fiili standarttır çağrı zinciri boyunca iptal, son tarihler ve kapsama bağlı değerler, birden fazla goroutine karşı. Tüm standart "ağ oluşturma" paketleri (net/http, database/sql, os/exec) context.Context'ü şu şekilde kabul edin: onların ilk parametresi.

Arayüz

Go
type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key any) any
}
  • Done(): içerik iptal edildiğinde kapatılan kanal.
  • Err(): iptal nedeni (context.Canceled veya context.DeadlineExceeded).
  • Deadline(): isteğe bağlı son tarih.
  • Value(): kapsama bağlı değerlerin aranması (idareli kullanın).

Dört temel işlev

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

Türetilen tüm formlar bir cancel işlevi döndürür: her zaman onu çağırın (ideal olarak defer ile) dahili kaynakları serbest bırakmak için bağlamın süresi zaten doldu.

Zaman aşımı modeli

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
}

queryUser 2 saniyeden uzun sürerse ctx.Done() kapatılır ve işlevin işlemi iptal etmesi gerekir.

Bağlama saygı göstererek: Bitti() seçeneğini seçin

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
        }
    }
}

Kural: İşlevinizin uzun süre engelleyebileceği her yerde, ctx.Done()'u işlemelidir. Aksi halde bağlam "açıktır" hiçbir şey.

Birinci parametre kuralı

Go
func Fetch(ctx context.Context, url string) ([]byte, error) { ... }
//        ^^^^^^^^^^^^^^^^^^^
// SEMPRE primo, mai dentro a una struct, mai opzionale
  • ctx HER ZAMAN ilk parametre olarak ctx adlı.
  • Asla Context öğesini bir yapının alanı olarak koymayın (çok nadir istisnalar).
  • Asla nil'yi geçmeyin: saplama olarak context.TODO() kullanın.

context.WithValue: idareli

Go
type userKey struct{}

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

Yönergeler:

  • YALNIZCA istek kapsamlı veriler için (istek kimliği, izleme kimliği, kullanıcı kimliği).
  • ASLA fonksiyon parametreleri için: bunları normal şekilde iletin.
  • Çarpışmaları önlemek için dışa aktarılmayan özel türde anahtarlar.

Zincir boyunca yayılma

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, istemci olduğunda r.Context() otomatik olarak iptal edilir. bağlantı kesildiğinde veya işleyici geri döndüğünde. Bunu herkese yayarak aşağı yönlü aramalarda tüm işlem ağacı iptal edilir kademeli: bağlantı kesildikten sonra iş israfı olmaz.

Deneyin

Egzersiz#go.m7.l5.e1
Denemeler: 0Yükleniyor…

context.Background()'dan türetilmiş 1 saniyelik zaman aşımına sahip bir bağlam oluşturun ve defer ile cancel çağrısını yapmayı unutmayın.

Düzenleyici yükleniyor…
İpucu göster

'context.WithTimeout(parent, d)', '(ctx, cancel)' değerini döndürür; her zaman ara iptal et.

3 denemeden sonra çözüm mevcut

Egzersiz#go.m7.l5.e2
Denemeler: 0Yükleniyor…

Bağlamın iptal edilmesini beklemek için seçimde <-ctx.Done() öğesini kullanın.

Düzenleyici yükleniyor…
İpucu göster

`ctx.Done()`, içerik iptal edildiğinde kapanan bir kanaldır.

3 denemeden sonra çözüm mevcut

Quiz#go.m7.l5.e3
Hazır

Geleneksel olarak, ctx parametresi bir işlev imzasında nereye gider?

Go
func Fetch(???, url string) ([]byte, error)
Cevap seçenekleri

Özet

  • context.Context iptali, son tarihi ve kapsama bağlı değerleri yayar.
  • Kök olarak Background()/TODO(); WithCancel/WithTimeout/WithDeadline türetmek için.
  • Kaynakları serbest bırakmak için her zaman defer cancel().
  • "Uzun" işlevler select üzerinde ctx.Done() olmalıdır veya ctx'i standart paketlere geçirmelidir.
  • Kural: ctx FIRST parametresi olarak, asla bir yapının içinde değil.
  • WithValue yalnızca istek kapsamlı veriler için (istek kimliği, izleme kimliği).
  • net/http'de, istemci bağlantısı kesildiğinde r.Context() iptal edilir.