Pachetul context este cea mai importantă bibliotecă de sincronizare și control din limbajul Go. În aplicațiile web și microservicii distribuite, o singură cerere primită de la un utilizator poate declanșa interogări către trei baze de date, două apeluri gRPC către alte servicii și operațiuni de disc. Dacă utilizatorul își închide browserul sau conexiunea cade, continuarea acestor operațiuni reprezintă o risipă masivă de resurse. Pachetul context permite propagarea instantanee a semnalului de anulare în cascadă de-a lungul întregului arbore de apeluri.
1. Regulile de Aur ale Pachetului context
ctx context.Contexttrebuie să fie întotdeauna primul parametru al unei funcții (ex:func InterogheazaDB(ctx context.Context, id int) error).- Nu stocați un Context în interiorul unei structuri; transmiteți-l întotdeauna explicit prin parametri de funcție.
- Dacă creați un context derivat (
WithCancel,WithTimeout,WithDeadline), apelați întotdeaunadefer cancel()imediat pe linia următoare pentru a elibera resursele timer-ului intern!
package main
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
)
func obtineSoldUtilizator(ctx context.Context, db *sql.DB, utilizatorID int) (float64, error) {
// 1. Limităm timpul alocat interogării la maximum 2 secunde:
ctxTimeout, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel() // Eliberează resursele de ceas imediat ce funcția se termină
var sold float64
// 2. Transmitem contextul către QueryRowContext:
// Dacă trec 2 secunde, driverul de bază de date anulează automat interogarea pe serverul SQL!
err := db.QueryRowContext(ctxTimeout, "SELECT sold FROM conturi WHERE id = $1", utilizatorID).Scan(&sold)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return 0, fmt.Errorf("baza de date a raspuns prea lent: %w", err)
}
return 0, err
}
return sold, nil
}
2. Stocarea Sigură a Valorilor cu context.WithValue
Utilizarea context.WithValue pentru a transmite parametri opționali obișnuiți de funcții este o greșeală gravă de proiectare (anti-pattern). Contextul trebuie utilizat exclusiv pentru metadate de tranzit la nivel de cerere (Request-Scoped Data), cum ar fi un Trace ID sau datele utilizatorului autentificat extrase dintr-un token JWT:
package auth
import "context"
// Definim un tip ne-exportat pentru cheie (previne coliziunile accidentale între pachete):
type contextKey struct{}
var userKey = contextKey{}
type DateUtilizator struct {
Email string
Rol string
}
// Injectarea în context:
func WithUser(ctx context.Context, u DateUtilizator) context.Context {
return context.WithValue(ctx, userKey, u)
}
// Extragerea de tip sigur din context:
func FromContext(ctx context.Context) (DateUtilizator, bool) {
u, ok := ctx.Value(userKey).(DateUtilizator)
return u, ok
}
Întrebări & Exemple de Cod:
Stăpânirea Pachetului context în Go: Propagarea Timpilor Limită, Anularea în Cascadă și Tracing în MicroserviciiAi o nelămurire despre utilizarea comenzii
Stăpânirea Pachetului context în Go: Propagarea Timpilor Limită, Anularea în Cascadă și Tracing în Microserviciisau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!
Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.