Sobes.tech
Middle

Hogyan épülnek fel a kontextusok a Go nyelvben?

sobes.tech MI

Válasz az MI-től

A context (context.Context) a Go nyelvben az információk átadására szolgál határértékek, lemondások és más adatok között az API határokon belül. Egy fához hasonlít, ahol minden kontextus egy másik gyermeke, kivéve a gyökér (context.Background() vagy context.TODO()).

A context.Context interfész főbb módszerei:

  • Deadline() (deadline time.Time, ok bool): Visszaadja a kontextus határidejét.
  • Done() <-chan struct{}: Visszaad egy csatornát, ami záródik a kontextus lemondásakor.
  • Err() error: Visszaadja a hibát, ami a kontextus lemondásához vezetett.
  • Value(key any) any: Visszaadja a kulcshoz kapcsolódó értéket a kontextusban.

A context csomag függvényeivel hozható létre:

  • context.Background(): Gyökér üres kontextus, amely a fő folyamat alapja.
  • context.TODO(): Ideiglenes helyettesítés, ha nem ismert, melyik kontextust kellene használni.
  • context.WithCancel(parent Context): Gyermek kontextus és lemondási funkció létrehozása.
  • context.WithDeadline(parent Context, d time.Time): Gyermek kontextus határidővel.
  • context.WithTimeout(parent Context, timeout time.Duration): Gyermek kontextus időkorláttal.
  • context.WithValue(parent Context, key, val any): Gyermek kontextus értékkel.

A Context főbb megvalósításai:

  • emptyCtx: Alapértelmezett, nem lemondható és érték nélküli. A Background és a TODO használják.
  • cancelCtx: Támogatja a lemondást. Alap kontextusból és lemondási csatornából áll.
  • timerCtx: Támogatja a határidőt/időzítőt. Tartalmazza a cancelCtx-t és az időzítőt.
  • valueCtx: Támogatja az értékek átadását. Tartalmazza az alap kontextust és kulcs-érték párokat.

A szülő kontextus lemondásakor automatikusan lemondanak az összes gyermek kontextusok is. Ez lehetővé teszi a lemondási jelek vagy határidők láncolatos terjesztését.

A context.WithCancel használatának példája:

package main

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

func main() {
	// Gyökér kontextus és lemondási funkció létrehozása
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // Biztosítja a lemondást a main végén

	go func() {
		select {
		case <-ctx.Done(): // Várakozás a kontextus lemondására
			fmt.Println("Feladat lemondva:", ctx.Err())
			return
		case <-time.After(5 * time.Second): // Vagy 5 másodperc múlva befejeződik
			fmt.Println("Feladat befejeződött")
		}
	}()

	// A kontextus lemondása más helyről
	time.Sleep(1 * time.Second)
	fmt.Println("A kontextus lemondása...")
	cancel()

	// Időt adunk a goroutine-nak a lemondás feldolgozására
	time.Sleep(100 * time.Millisecond)
}

A context.WithValue használatának példája:

package main

import (
	"context"
	"fmt"
)

type userIDKey string

func processRequest(ctx context.Context) {
	if userID, ok := ctx.Value(userIDKey("UserID")).(string); ok {
		fmt.Println("Feldolgozás a User ID-hez:", userID)
	} else {
		fmt.Println("User ID nem található a kontextusban")
	}
}

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

A kontextusok szálbiztosak és változatlanok, ami fontos a konkurens kód esetén. Nem céljuk a nyers paraméterek átadása, hanem inkább a meta-információk, amelyek befolyásolják a folyamat végrehajtását.