Middle
Parlez-moi des cas d'utilisation du contexte dans Go.
sobes.tech IA
Réponse de l'IA
Le contexte en Go est utilisé pour gérer le cycle de vie des requêtes et contrôler l'exécution des goroutines. Les principaux cas d'utilisation:
- Annulation: Permet d'annuler la chaîne de goroutines liée à une requête spécifique. Par exemple, lors de la fermeture de la connexion ou en cas de timeout.
- Timeout: Définit un délai limite pour l'opération. Si l'opération ne se termine pas dans ce délai, le contexte est annulé. Cela évite les attentes infinies.
- Transmission de données spécifiques à la requête: Permet de transmettre des données liées à une requête spécifique (par exemple, ID utilisateur, identifiant de traçage) à travers la chaîne d'appels sans modifier leurs signatures.
Exemples d'utilisation:
-
Annulation par signal:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Travailleur %d interrompu\n", id) return default: fmt.Printf("Travailleur %d en cours...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Garantie d'annulation go worker(ctx, 1) go worker(ctx, 2) time.Sleep(2 * time.Second) cancel() // Annule le contexte time.Sleep(500 * time.Millisecond) // Donne le temps aux goroutines de finir } -
Timeout:
package main import ( "context" "fmt" "time" ) func longOperation(ctx context.Context) error { select { case <-time.After(3 * time.Second): // Simulation d'une longue opération fmt.Println("Opération terminée avec succès") return nil case <-ctx.Done(): fmt.Println("Opération annulée par le contexte:", 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("Erreur:", err) } } -
Transmission de données:
package main import ( "context" "fmt" ) type UserKey string const userIDKey UserKey = "userID" func processRequest(ctx context.Context) { userID := ctx.Value(userIDKey).(int) fmt.Printf("Traitement de la requête pour l'utilisateur ID: %d\n", userID) // Traitement supplémentaire de la requête avec userID } func main() { ctx := context.WithValue(context.Background(), userIDKey, 123) processRequest(ctx) }
Il est important d'utiliser context.Background() ou context.TODO() comme contexte racine et de le transmettre en aval dans la chaîne d'appels. Il ne faut pas stocker le contexte dans des structures de données s'il n'est pas directement lié au cycle de vie de cette structure.