Middle
Vorbește-mi despre cazurile de utilizare ale contextului în Go.
sobes.tech AI
Răspuns de la AI
Contextul în Go este utilizat pentru gestionarea ciclului de viață al solicitărilor și controlul execuției goroutine-urilor. Principalele cazuri de utilizare:
- Anulare: Permite anularea lanțului de goroutine-uri asociate unei solicitări specifice. De exemplu, la închiderea conexiunii sau în cazul timeout-ului.
- Timeout: Stabilește un termen limită pentru finalizarea operației. Dacă operația nu se finalizează în acest interval, contextul este anulat. Acest lucru previne așteptările infinite.
- Transmiterea datelor specifice solicitării: Permite transmiterea datelor legate de o solicitare concretă (de exemplu, ID-ul utilizatorului, identificatorul de urmărire) prin lanțul de apeluri, fără a modifica semnăturile acestora.
Exemple de utilizare:
-
Anulare prin semnal:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Lucrător %d întrerupt\n", id) return default: fmt.Printf("Lucrător %d lucrând...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Asigură anularea go worker(ctx, 1) go worker(ctx, 2) time.Sleep(2 * time.Second) cancel() // Anulează contextul time.Sleep(500 * time.Millisecond) // Oferă timp goroutine-urilor să se termine } -
Timeout:
package main import ( "context" "fmt" "time" ) func longOperation(ctx context.Context) error { select { case <-time.After(3 * time.Second): // Simulare a unei operații lungi fmt.Println("Operație finalizată cu succes") return nil case <-ctx.Done(): fmt.Println("Operație anulată de context:", ctx.Err()) return ctx.Err() } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() err := longOperation(ctx) if err != nil { fmt.Println("Eroare:", err) } } -
Transmiterea datelor:
package main import ( "context" "fmt" ) type UserKey string const userIDKey UserKey = "userID" func processRequest(ctx context.Context) { userID := ctx.Value(userIDKey).(int) fmt.Printf("Procesarea solicitării pentru ID-ul utilizatorului: %d\n", userID) // Procesarea suplimentară a solicitării cu userID } func main() { ctx := context.WithValue(context.Background(), userIDKey, 123) processRequest(ctx) }
Este important să folosiți context.Background() sau context.TODO() ca context rădăcină și să îl transmiteți în jos pe lanțul de apeluri. Nu trebuie să stocați contextul în structuri de date dacă nu este direct legat de ciclul de viață al acestei structuri.