Modulelessen (5/5)
`context.Context`: annulering en deadlines
Het pakket context is de de facto standaard voor propagatie
annuleringen, deadlines en bereikgebonden waarden in de belketen,
over meerdere goroutines. Alle standaard "netwerk" pakketten
(net/http, database/sql, os/exec) accepteer een context.Context als
hun eerste parameter.
De interface
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key any) any
}Done(): kanaal dat wordt gesloten wanneer de context wordt geannuleerd.Err(): reden voor annulering (context.Canceledofcontext.DeadlineExceeded).Deadline(): optionele deadline.Value(): opzoeken van bereikgebonden waarden (spaarzaam gebruiken).
De vier basisfuncties
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-boundAlle afgeleide vormen retourneren een cancel functie: roep deze altijd aan
(idealiter met defer) om interne bronnen vrij te geven, zelfs als de
context is al verlopen.
Time-out patroon
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
}Als queryUser langer dan 2 seconden duurt, wordt ctx.Done() gesloten en
de functie moet de bewerking afbreken.
De context respecteren: selecteer op Done()
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
}
}
}De regel: overal waar uw functie voor langere tijd blokkeert, wordt het moet ctx.Done() verwerken. Anders wordt de context "aangezet". niets.
Conventie van eerste parameters
func Fetch(ctx context.Context, url string) ([]byte, error) { ... }
// ^^^^^^^^^^^^^^^^^^^
// SEMPRE primo, mai dentro a una struct, mai opzionalectxALTIJD als de eerste parameter, genaamdctx.- Nooit plaats
Contextals een veld van een structuur (zeer zeldzame uitzonderingen). - Nooit passeer
nil: gebruikcontext.TODO()als stub.
context.WithValue: spaarzaam
type userKey struct{}
ctx := context.WithValue(ctx, userKey{}, currentUser)
// più sotto:
if u, ok := ctx.Value(userKey{}).(*User); ok { ... }Richtlijnen:
- ALLEEN voor verzoekgerichte gegevens (verzoek-ID, trace-ID, gebruikersidentiteit).
- NOOIT voor functieparameters: geef ze normaal door.
- Sleutels van een aangepast, niet-geëxporteerd type om botsingen te voorkomen.
Voortplanting langs de keten
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 annuleert automatisch r.Context() wanneer de client
de verbinding verbreekt of wanneer de handler terugkeert. Door het aan iedereen te verspreiden
downstream-oproepen wordt de hele boom van bewerkingen geannuleerd
cascade: geen verspild werk na ontkoppeling.
Probeer het
Creëer een context met een time-out van 1 seconde afgeleid van context.Background() en vergeet niet om cancel met uitstel aan te roepen.
Toon hint
`context.WithTimeout(parent, d)` retourneert `(ctx, annuleren)`; altijd bellen annuleren.
Oplossing beschikbaar na 3 pogingen
Gebruik <-ctx.Done() in een selectie om te wachten tot de context wordt geannuleerd.
Toon hint
`ctx.Done()` is een kanaal dat sluit wanneer de context wordt geannuleerd.
Oplossing beschikbaar na 3 pogingen
Waar gaat de ctx-parameter volgens afspraak naartoe in een functiehandtekening?
func Fetch(???, url string) ([]byte, error)Samenvatten
context.Contextpropageert annulerings-, deadline- en bereikgebonden waarden.Background()/TODO()als root;WithCancel/WithTimeout/WithDeadlineom af te leiden.- Altijd
defer cancel()om bronnen vrij te geven. - "Lange" functies moeten
selectopctx.Done()of ctx doorgeven aan standaardpakketten. - Conventie:
ctxals de FIRST parameter, nooit binnen een struct. WithValuealleen voor gegevens op aanvraaggebied (aanvraag-ID, trace-ID).- In
net/httpwordtr.Context()geannuleerd wanneer de clientverbinding wordt verbroken.