Sobes.tech
Middle

Hoe zijn de contexten opgebouwd in de Go-taal?

sobes.tech AI

Antwoord van AI

De (context.Context) in Go wordt gebruikt om informatie over deadlines, annuleringen en andere gegevens tussen API-grenzen te verzenden. Het vertegenwoordigt een boom: elke context is een kind van een andere, behalve de wortel (context.Background() of context.TODO()).

De belangrijkste methoden van de interface context.Context:

  • Deadline() (deadline time.Time, ok bool): Geeft de deadline van de context terug.
  • Done() <-chan struct{}: Geeft een kanaal dat wordt gesloten wanneer de context wordt geannuleerd.
  • Err() error: Geeft de fout terug die tot de annulering van de context heeft geleid.
  • Value(key any) any: Geeft de waarde terug die aan de sleutel in de context is gekoppeld.

Ze worden gemaakt met functies uit de context-package:

  • context.Background(): De lege hoofdkontekst, gebruikt als basis voor het hoofdproces.
  • context.TODO(): Wordt gebruikt als tijdelijke aanduiding wanneer niet bekend is welke context te gebruiken.
  • context.WithCancel(parent Context): Maakt een kindcontext en een annuleringsfunctie.
  • context.WithDeadline(parent Context, d time.Time): Maakt een kindcontext met een deadline.
  • context.WithTimeout(parent Context, timeout time.Duration): Maakt een kindcontext met een timeout.
  • context.WithValue(parent Context, key, val any): Maakt een kindcontext met een waarde.

Belangrijkste implementaties van Context:

  • emptyCtx: Basis, niet-annuleerbaar en zonder waarden. Gebruikt Background en TODO.
  • cancelCtx: Ondersteunt annulering. Bestaat uit een basiscontext en een annuleringskanaal.
  • timerCtx: Ondersteunt deadline/timeout. Bevat cancelCtx en een timer.
  • valueCtx: Ondersteunt het doorgeven van waarden. Bevat een basiscontext en sleutel-waardeparen.

Bij annulering van de oudercontext worden alle kindcontexten automatisch geannuleerd. Dit maakt het mogelijk om annulering- of deadline-signalen door te geven in de keten van oproepen.

Voorbeeld van gebruik van context.WithCancel:

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	// Maak de hoofdkontekst en een annuleringsfunctie
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // Zorg voor annulering bij het verlaten van main

	go func() {
		select {
		case <-ctx.Done(): // Wacht op annulering van de context
			fmt.Println("Taak geannuleerd:", ctx.Err())
			return
		case <-time.After(5 * time.Second): // Of na 5 seconden
			fmt.Println("Taak voltooid")
		}
	}()

	// Annuleer de context vanaf een andere plek
	time.Sleep(1 * time.Second)
	fmt.Println("Annuleren van de context...")
	cancel()

	// Geef de goroutine tijd om de annulering te verwerken
	time.Sleep(100 * time.Millisecond)
}

Voorbeeld van gebruik van context.WithValue:

package main

import (
	"context"
	"fmt"
)

type userIDKey string

func processRequest(ctx context.Context) {
	if userID, ok := ctx.Value(userIDKey("UserID")).(string); ok {
		fmt.Println("Verwerking van verzoek voor User ID:", userID)
	} else {
		fmt.Println("User ID niet gevonden in context")
	}
}

func main() {
	ctx := context.WithValue(context.Background(), userIDKey("UserID"), "12345")
	processRequest(ctx)
}

Contexten zijn thread-safe en onveranderlijk, wat belangrijk is voor gelijktijdige code. Ze zijn niet bedoeld om rauwe parameters van functies door te geven, maar eerder voor metadata die de uitvoering van het proces beïnvloeden.