Sobes.tech
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:

  1. 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
    }
    
  2. 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)
    	}
    }
    
  3. 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.