Ce face context.Background
context.Background() returnează un context gol: nu este anulat niciodată (Done() returnează nil), nu are termen limită și nu conține valori. Este rădăcina arborelui de contexte: îl folosești în main, la pornirea programului, în teste și în sarcinile de fundal, apoi creezi din el contexte cu limită de timp sau anulare (WithTimeout, WithCancel, WithValue).
context.TODO() este identic ca funcționare, dar transmite un mesaj cititorului: „aici ar trebui să vină un context real, dar încă nu am unul”. Se folosește temporar, când adaugi suport pentru context unei funcții ai cărei apelanți nu dau încă un context. Uneltele de analiză pot căuta apelurile TODO rămase.
Într-un handler HTTP nu pornești de la Background: folosești r.Context(), care se anulează când clientul pleacă.
Ce returnează
Un context.Context gol. Ambele funcții returnează mereu aceeași valoare.
Exemple
Exemplul 1: Proprietățile contextului rădăcină
package main
import (
"context"
"fmt"
)
func main() {
contexte := []struct {
nume string
ctx context.Context
}{{"Background", context.Background()}, {"TODO", context.TODO()}}
for _, c := range contexte {
nume, ctx := c.nume, c.ctx
_, areTermen := ctx.Deadline()
fmt.Printf("%-10s Done=nil:%v Err=%v termen:%v valoare:%v text:%s\n",
nume, ctx.Done() == nil, ctx.Err(), areTermen, ctx.Value("x"), ctx)
}
}
Rezultat
Background Done=nil:true Err=<nil> termen:false valoare:<nil> text:context.Background
TODO Done=nil:true Err=<nil> termen:false valoare:<nil> text:context.TODO
Exemplul 2: Punctul de pornire în main
Din Background se creează un context cu limită de timp, transmis apoi funcțiilor.
package main
import (
"context"
"fmt"
"time"
)
func sincronizeazaStoc(ctx context.Context) error {
select {
case <-time.After(20 * time.Millisecond):
fmt.Println("Stoc sincronizat")
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := sincronizeazaStoc(ctx); err != nil {
fmt.Println("eroare:", err)
}
}
Rezultat
Stoc sincronizat
Exemplul 3: TODO pentru cod în curs de schimbare
package main
import (
"context"
"fmt"
)
// TrimiteEmail primește acum un context, dar apelantul vechi nu are încă unul.
func TrimiteEmail(ctx context.Context, catre string) error {
if err := ctx.Err(); err != nil {
return err
}
fmt.Println("E-mail trimis către", catre)
return nil
}
func notificareVeche(catre string) {
TrimiteEmail(context.TODO(), catre) // de înlocuit cu contextul cererii
}
func main() {
notificareVeche("ana@example.ro")
}
Rezultat
E-mail trimis către ana@example.ro
Greșeli frecvente
- Folosești
context.Background()în adâncul codului (în handler-e, în funcții de bibliotecă) în loc să primești contextul ca parametru: anularea de sus nu mai ajunge la operații. - Transmiți
nilcând nu ai un context: funcțiile se pot opri cu panică. Dăcontext.TODO().
Comenzi înrudite
context.Context: Interfața care duce prin program semnalul de anulare, termenul limită și valori legate de o cerere (ctx).context.WithTimeout: Creează un context care se anulează singur după durata dată; limita de timp standard pentru cereri și interogări.context.WithCancel: Creează un context copil și o funcție cancel; apelul cancel() anunță toate goroutine-urile care îl folosesc să se oprească.context.WithValue: Creează un context copil care poartă o pereche cheie-valoare (ID de cerere, utilizator autentificat), citită cu ctx.Value(cheie).