Middle
Mesélj a kontextus használati eseteiről a Go-ban.
sobes.tech MI
Válasz az MI-től
A Go-ban a kontextus a kérések életciklusának kezelésére és a goroutine-ok végrehajtásának ellenőrzésére szolgál. A fő felhasználási esetek:
- Mégsem: Lehetővé teszi egy adott kéréshez kapcsolódó goroutine láncának megszakítását. Például a kapcsolat lezárásakor vagy időkorlát esetén.
- Időkorlát: Meghatározza a művelet végrehajtásának határidejét. Ha a művelet ezen időn belül nem fejeződik be, a kontextus megszakad. Ez megakadályozza a végtelen várakozást.
- Kérdés-specifikus adatok átadása: Lehetővé teszi az adott kérdéshez kapcsolódó adatok (például felhasználói azonosító, nyomkövető azonosító) átadását a hívási láncon keresztül anélkül, hogy megváltoztatná azok aláírását.
Használati példák:
-
Jelzés szerinti megszakítás:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Munkás %d megszakítva\n", id) return default: fmt.Printf("Munkás %d dolgozik...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Biztosítja a megszakítást go worker(ctx, 1) go worker(ctx, 2) time.Sleep(2 * time.Second) cancel() // A kontextus megszakítása time.Sleep(500 * time.Millisecond) // Időt adunk a goroutine-oknak a befejezéshez } -
Időkorlát:
package main import ( "context" "fmt" "time" ) func longOperation(ctx context.Context) error { select { case <-time.After(3 * time.Second): // Hosszú művelet szimulálása fmt.Println("Művelet sikeresen befejeződött") return nil case <-ctx.Done(): fmt.Println("Művelet megszakítva a kontextus által:", 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("Hiba:", err) } } -
Adatok átadása:
package main import ( "context" "fmt" ) type UserKey string const userIDKey UserKey = "userID" func processRequest(ctx context.Context) { userID := ctx.Value(userIDKey).(int) fmt.Printf("Kérés feldolgozása a felhasználói azonosítóval: %d\n", userID) // További kérésfeldolgozás userID használatával } func main() { ctx := context.WithValue(context.Background(), userIDKey, 123) processRequest(ctx) }
Fontos, hogy a gyökérkonteknt context.Background() vagy context.TODO() használjuk, és azt lefelé adjuk át a hívási láncon. A kontextust nem szabad adatstruktúrákban tárolni, ha nem kapcsolódik közvetlenül az adott struktúra életciklusához.