Direkt zum Hauptinhalt springen
eLearner.app
Modul 7 · Lektion 5 von 535/50 im Kurs~14 min
Lektionen des Moduls (5/5)

`context.Context`: Abbruch und Deadlines

Das context-Paket ist der De-facto-Standard für die Weitergabe Kündigung, Fristen und Umfangswerte** entlang der Anrufkette, über mehrere Goroutinen hinweg. Alle Standard-Netzwerkpakete (net/http, database/sql, os/exec) akzeptieren einen context.Context als ihr erster Parameter.

Die Schnittstelle

Go
type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key any) any
}
  • Done(): Kanal, der geschlossen wird, wenn der Kontext abgebrochen wird.
  • Err(): Grund für die Stornierung (context.Canceled oder context.DeadlineExceeded).
  • Deadline(): optionale Frist.
  • Value(): Suche nach bereichsgebundenen Werten (sparsam verwenden).

Die vier Grundfunktionen

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

Alle abgeleiteten Formen geben eine cancel-Funktion zurück: Rufen Sie sie immer auf (idealerweise mit defer), um interne Ressourcen freizugeben, auch wenn die Der Kontext ist bereits abgelaufen.

Timeout-Muster

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
}

Wenn queryUser länger als 2 Sekunden dauert, wird ctx.Done() geschlossen und Die Funktion muss den Vorgang abbrechen.

Respektieren Sie den Kontext: Wählen Sie „Done()“ aus.

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

Die Regel: Überall dort, wo Ihre Funktion für längere Zeit blockieren könnte, wird sie verwendet muss mit ctx.Done() umgehen. Andernfalls ist der Kontext „eingeschaltet“. nichts.

Konvention für den ersten Parameter

Go
func Fetch(ctx context.Context, url string) ([]byte, error) { ... }
//        ^^^^^^^^^^^^^^^^^^^
// SEMPRE primo, mai dentro a una struct, mai opzionale
  • ctx IMMER als erster Parameter mit dem Namen ctx.
  • Niemals Context als Feld einer Struktur einfügen (sehr seltene Ausnahmen).
  • Niemals nil übergeben: Verwenden Sie context.TODO() als Stub.

context.WithValue: sparsam

Go
type userKey struct{}

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

Richtlinien:

  • NUR für anforderungsbezogene Daten (Anfrage-ID, Trace-ID, Benutzeridentität).
  • NIEMALS für Funktionsparameter: Übergeben Sie sie normal.
  • Schlüssel vom Typ benutzerdefinierter, nicht exportierter, um Kollisionen zu vermeiden.

Ausbreitung entlang der Kette

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 bricht r.Context() automatisch ab, wenn der Client die Verbindung unterbrochen wird oder wenn der Handler zurückkehrt. Indem man es an alle weitergibt Bei nachgeschalteten Aufrufen wird der gesamte Operationsbaum abgebrochen Kaskade: Keine verschwendete Arbeit nach der Trennung.

Probieren Sie es aus

Übung#go.m7.l5.e1
Versuche: 0Wird geladen…

Erstellen Sie einen Kontext mit einem von context.Background() abgeleiteten Timeout von 1 Sekunde und denken Sie daran, cancel mit defer aufzurufen.

Editor wird geladen…
Hinweis anzeigen

`context.WithTimeout(parent, d)` gibt `(ctx, cancel)` zurück; Rufen Sie immer abbrechen an.

Lösung nach 3 Versuchen verfügbar

Übung#go.m7.l5.e2
Versuche: 0Wird geladen…

Verwenden Sie <-ctx.Done() in einer Auswahl, um darauf zu warten, dass der Kontext abgebrochen wird.

Editor wird geladen…
Hinweis anzeigen

`ctx.Done()` ist ein Kanal, der geschlossen wird, wenn der Kontext abgebrochen wird.

Lösung nach 3 Versuchen verfügbar

Quiz#go.m7.l5.e3
Bereit

Wo steht der ctx-Parameter konventionsgemäß in einer Funktionssignatur?

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

Zusammenfassung

context.Context gibt Stornierungs-, Frist- und bereichsgebundene Werte weiter.

  • Background()/TODO() als Wurzel; WithCancel/WithTimeout/WithDeadline abzuleiten.
  • Immer defer cancel(), um Ressourcen freizugeben.
  • „Lange“ Funktionen müssen select auf ctx.Done() oder ctx an Standardpakete übergeben.
  • Konvention: ctx als ERSTER Parameter, niemals innerhalb einer Struktur. – Background()0 nur für anforderungsbezogene Daten (Anfrage-ID, Trace-ID). – In Background()1 wird Background()2 beim Trennen des Clients abgebrochen.