Junior
Czym jest kontekst w Go?
sobes.tech AI
Odpowiedź od AI
Kontekst (context.Context) w Go jest obiektem, który przenosi termin końcowy, sygnał anulowania (cancellation signal) oraz dane specyficzne dla żądania. Używa się go do zarządzania cyklem życia goroutine'ów i przekazywania informacji między nimi podczas wykonywania żądania/operacji.
Główne cechy:
- Bezpieczny dla współbieżności: Może być bezpiecznie przekazywany między goroutine'ami.
- Niezmienny: Po utworzeniu,
Contextnie może być zmieniany. Konteksty pochodne są tworzone na podstawie rodzica. - Hierarchiczny: Konteksty tworzą drzewo z korzeniem (
context.Background()lubcontext.TODO()). Anulowanie kontekstu nadrzędnego powoduje anulowanie wszystkich jego potomków.
Główne funkcje pakietu context:
context.Background(): Pusty kontekst, zwykle używany w funkcji main, w wysokopoziomowych żądaniach lub podczas testów. Nigdy nie jest anulowany.context.TODO(): Również pusty kontekst. Używany jako zastępczy, gdy nie wiadomo, którego kontekstu użyć, lub gdy funkcjonalność kontekstu jeszcze nie jest zaimplementowana.context.WithCancel(parent Context): Zwraca nowy kontekst potomny i funkcję anulowania. Wywołanie funkcji anulowania anuluje ten kontekst i wszystkie jego konteksty potomne.context.WithDeadline(parent Context, deadline time.Time): Zwraca kontekst potomny, który automatycznie jest anulowany, gdy osiągnięty zostanie określony czas. Zwraca również funkcję anulowania do ręcznego anulowania.context.WithTimeout(parent Context, timeout time.Duration): To samo coWithDeadline, ale z określeniem czasu trwania.context.WithValue(parent Context, key, val interface{}): Zwraca kontekst potomny z przypisaną wartością do klucza.
Zastosowania:
- Anulowanie operacji: Na przykład, timeout żądania HTTP lub przerwanie długotrwałej operacji.
- Przekazywanie danych: Na przykład, ID żądania do logowania, informacje o uwierzytelnianiu.
Przykład użycia context.WithTimeout:
package main
import (
"context"
"fmt"
"time"
)
func longRunningOperation(ctx context.Context, resultChan chan string) {
select {
case <-time.After(3 * time.Second):
// Operacja zakończyła się sukcesem
resultChan <- "Operacja zakończona"
case <-ctx.Done():
// Kontekst został anulowany
err := ctx.Err() // Uzyskujemy przyczynę anulowania
resultChan <- fmt.Sprintf("Operacja anulowana: %v", err)
}
}
func main() {
// Tworzymy kontekst z czasem oczekiwania 2 sekundy
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // Zapewniamy wywołanie funkcji anulującej
resultChan := make(chan string, 1)
go longRunningOperation(ctx, resultChan)
// Czekamy na wynik lub anulowanie
select {
case res := <-resultChan:
fmt.Println(res)
case <-ctx.Done():
fmt.Printf("Główny kontekst zakończył się: %v\n", ctx.Err())
}
// Czekamy trochę, aby goroutine mogła się zakończyć, jeśli została anulowana
time.Sleep(1 * time.Second)
}
W tym przykładzie, longRunningOperation sprawdza, czy kontekst został anulowany. Jeśli czas oczekiwania głównego kontekstu (2 sekundy) upłynie wcześniej niż zakończy się sama operacja (3 sekundy), goroutine otrzymuje sygnał anulowania przez ctx.Done() i kończy się.