Sobes.tech
Middle

Go dilində kontekstlər necə qurulub?

sobes.tech Süni İntellekt

AI-dan cavab

Go dilində (context.Context) kontekst, API sərhədləri arasında məlumatların ötürülməsi üçün istifadə olunur. O, ağac şəklində təmsil olunur: hər bir kontekst başqa birinin uşağıdır, istisna olmaqla kök (context.Background() və ya context.TODO()).

context.Context interfeysinin əsas metodları:

  • Deadline() (deadline time.Time, ok bool): Kontekstin vaxt məhdudiyyətini qaytarır.
  • Done() <-chan struct{}: Kontekst ləğv olunduqda bağlanan kanalı qaytarır.
  • Err() error: Kontekstin ləğv olunmasına səbəb olan xətanı qaytarır.
  • Value(key any) any: Kontekstdə açarla əlaqəli dəyəri qaytarır.

Onlar context paketinin funksiyaları ilə yaradılır:

  • context.Background(): Boş əsas kontekst, əsas proses üçün istifadə olunur.
  • context.TODO(): Nə vaxt istifadə ediləcəyini bilmədikdə yer tutucu kimi istifadə olunur.
  • context.WithCancel(parent Context): Uşaq kontekst və ləğv funksiyası yaradır.
  • context.WithDeadline(parent Context, d time.Time): Vaxt məhdudiyyətli uşaq kontekst yaradır.
  • context.WithTimeout(parent Context, timeout time.Duration): Vaxt limiti ilə uşaq kontekst yaradır.
  • context.WithValue(parent Context, key, val any): Dəyər ilə uşaq kontekst yaradır.

Əsas Context tətbiqləri:

  • emptyCtx: Əsas, ləğv edilə bilməz və dəyərlərsizdir. BackgroundTODO istifadə olunur.
  • cancelCtx: Ləğv etməyi dəstəkləyir. Əsas kontekst və ləğv kanalı ilə təşkil olunub.
  • timerCtx: Vaxt məhdudiyyəti və ya vaxt limiti dəstəkləyir. cancelCtx və timer ehtiva edir.
  • valueCtx: Dəyərlərin ötürülməsini dəstəkləyir. Əsas kontekst və açar-dəyər cütlüklərini ehtiva edir.

Valideyn kontekst ləğv olunduqda, bütün uşaqlar avtomatik olaraq ləğv edilir. Bu, ləğv siqnallarını və ya vaxt limitlərini zəncir boyunca yaymağa imkan verir.

context.WithCancel istifadəsinə nümunə:

package main

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

func main() {
	// Əsas kontekst və ləğv funksiyası yaradılır
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // Main-dən çıxarkən ləğv etməyi təmin edir

	go func() {
		select {
		case <-ctx.Done(): // Kontekstin ləğvini gözləyir
			fmt.Println("Tapşırıq ləğv edildi:", ctx.Err())
			return
		case <-time.After(5 * time.Second): // Yaxud 5 saniyə sonra
			fmt.Println("Tapşırıq tamamlandı")
		}
	}()

	// Başqa yerdən konteksti ləğv et
	time.Sleep(1 * time.Second)
	fmt.Println("Konteksti ləğv edir...")
	cancel()

	// Ləğvi işləmək üçün vaxt veririk
	time.Sleep(100 * time.Millisecond)
}

context.WithValue istifadəsinə nümunə:

package main

import (
	"context"
	"fmt"
)

type userIDKey string

func processRequest(ctx context.Context) {
	if userID, ok := ctx.Value(userIDKey("UserID")).(string); ok {
		fmt.Println("İstək işlənir üçün User ID:", userID)
	} else {
		fmt.Println("Kontekstdə User ID tapılmadı")
	}
}

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

Kontekstlər çoxluq təhlükəsiz və dəyişməzdir, bu da çoxlu iş parçacığı kodu üçün vacibdir. Onlar funksiyaların işlənməsinə təsir edən meta məlumatlar üçün nəzərdə tutulub, xam parametrlərin ötürülməsi üçün deyil.