Middle
Erzählen Sie mir von Anwendungsfällen des Kontexts in Go.
sobes.tech KI
Antwort von AI
Der Kontext in Go wird verwendet, um den Lebenszyklus von Anfragen zu verwalten und die Ausführung von Goroutines zu steuern. Die Hauptanwendungsfälle:
- Abbruch: Ermöglicht das Abbrechen der Kette von Goroutines, die mit einer bestimmten Anfrage verbunden sind. Zum Beispiel beim Schließen der Verbindung oder bei Timeout.
- Timeout: Legt eine Frist für die Ausführung fest. Wenn die Operation innerhalb dieser Frist nicht abgeschlossen wird, wird der Kontext abgebrochen. Dies verhindert unendliche Wartezeiten.
- Weitergabe von anfrage-spezifischen Daten: Ermöglicht das Weitergeben von Daten, die sich auf eine bestimmte Anfrage beziehen (z.B. Benutzer-ID, Trace-Identifikator), durch die Aufrufkette, ohne deren Signaturen zu ändern.
Anwendungsbeispiele:
-
Abbruch durch Signal:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Arbeiter %d unterbrochen\n", id) return default: fmt.Printf("Arbeiter %d arbeitet...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Gewährleistet Abbruch go worker(ctx, 1) go worker(ctx, 2) time.Sleep(2 * time.Second) cancel() // Kontext abbrechen time.Sleep(500 * time.Millisecond) // Zeit für Goroutines zum Beenden } -
Timeout:
package main import ( "context" "fmt" "time" ) func longOperation(ctx context.Context) error { select { case <-time.After(3 * time.Second): // Simulation einer langen Operation fmt.Println("Operation erfolgreich abgeschlossen") return nil case <-ctx.Done(): fmt.Println("Operation vom Kontext abgebrochen:", 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("Fehler:", err) } } -
Weitergabe von Daten:
package main import ( "context" "fmt" ) type UserKey string const userIDKey UserKey = "userID" func processRequest(ctx context.Context) { userID := ctx.Value(userIDKey).(int) fmt.Printf("Verarbeite Anfrage für Benutzer-ID: %d\n", userID) // Weiterverarbeitung der Anfrage mit userID } func main() { ctx := context.WithValue(context.Background(), userIDKey, 123) processRequest(ctx) }
Es ist wichtig, context.Background() oder context.TODO() als Wurzelkontext zu verwenden und ihn nach unten in die Aufrufkette zu übergeben. Der Kontext sollte nicht in Datenstrukturen gespeichert werden, wenn er nicht direkt mit dem Lebenszyklus dieser Struktur verbunden ist.