Sobes.tech
Middle

Kā ir strukturēti konteksti Go valodā?

sobes.tech AI

Atbilde no AI

Konteksts (context.Context) Go valodā tiek izmantots, lai nodotu informāciju par termiņiem, atcelšanu un citiem datiem starp API robežām. Tas ir koka struktūra: katrs konteksts ir bērns citam, izņemot saknes (context.Background() vai context.TODO()).

Galvenās context.Context saskarnes metodes:

  • Deadline() (deadline time.Time, ok bool): Atgriež konteksta termiņu.
  • Done() <-chan struct{}: Atgriež kanālu, kas tiek aizvērts, kad konteksts tiek atcelts.
  • Err() error: Atgriež kļūdu, kas noveda pie konteksta atcelšanas.
  • Value(key any) any: Atgriež saistīto vērtību ar atslēgu kontekstā.

Tiek izveidots ar context pakotnes funkcijām:

  • context.Background(): Saknes tukšais konteksts, kas tiek izmantots kā galvenās procesa bāze.
  • context.TODO(): Izmanto kā aizstājēju, kad nav zināms, kuru kontekstu izmantot.
  • context.WithCancel(parent Context): Izveido bērna kontekstu un atcelšanas funkciju.
  • context.WithDeadline(parent Context, d time.Time): Izveido bērna kontekstu ar termiņu.
  • context.WithTimeout(parent Context, timeout time.Duration): Izveido bērna kontekstu ar laika ierobežojumu.
  • context.WithValue(parent Context, key, val any): Izveido bērna kontekstu ar vērtību.

Galvenās Context realizācijas:

  • emptyCtx: Pamata, neatsaucams un bez vērtībām. Tiek izmantots Background un TODO.
  • cancelCtx: Atbalsta atcelšanu. Sastāv no pamata konteksta un atcelšanas kanāla.
  • timerCtx: Atbalsta termiņu/laika ierobežojumu. Satur cancelCtx un taimeri.
  • valueCtx: Atbalsta vērtību nodošanu. Satur pamata kontekstu un atslēgas-vērtības pāri.

Kad vecā konteksts tiek atcelts, automātiski tiek atcelti visi bērni. Tas ļauj izplatīt atcelšanas signālus vai termiņus pa izsaukumu ķēdi.

Piemērs ar context.WithCancel:

package main

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

func main() {
	// Izveido saknes kontekstu un atcelšanas funkciju
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // Garantē atcelšanu, izejot no main

	go func() {
		select {
		case <-ctx.Done(): // Gaida konteksta atcelšanu
			fmt.Println("Uzdevums atcelts:", ctx.Err())
			return
		case <-time.After(5 * time.Second): // Vai pabeidz pēc 5 sekundēm
			fmt.Println("Uzdevums pabeigts")
		}
	}()

	// Atceļ kontekstu no citas vietas
	time.Sleep(1 * time.Second)
	fmt.Println("Atceļ kontekstu...")
	cancel()

	// Dod laiku gorutīnai apstrādāt atcelšanu
	time.Sleep(100 * time.Millisecond)
}

Piemērs ar 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("Apstrādā pieprasījumu lietotāja ID:", userID)
	} else {
		fmt.Println("Lietotāja ID nav kontekstā")
	}
}

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