Sobes.tech
Junior

Ce este contextul în Go?

sobes.tech AI

Răspuns de la AI

Contextul (context.Context) în Go este un obiect care transportă termenul limită, semnalul de anulare și date specifice solicitării. Este utilizat pentru gestionarea ciclului de viață al goroutine-urilor și pentru transmiterea informațiilor între ele în timpul executării unei solicitări/operațiuni.

Caracteristici principale:

  • Sigur pentru concurență: Poate fi transferat în siguranță între goroutine-uri.
  • Imutabil: Odată creat, un Context nu poate fi schimbat. Contextele derivate sunt create pe baza părintelui.
  • ** ierarhic**: Contextele formează un copac cu rădăcină (context.Background() sau context.TODO()). Anularea contextului părinte duce la anularea tuturor copiilor săi.

Funcții principale ale pachetului context:

  • context.Background() : Context gol, utilizat de obicei în funcția main, în solicitări de nivel înalt sau în teste. Nu este niciodată anulat.
  • context.TODO() : De asemenea, un context gol. Este utilizat ca un înlocuitor atunci când nu se știe ce context să se folosească sau dacă funcționalitatea contextului nu a fost încă implementată.
  • context.WithCancel(parent Context) : Returnează un nou context copil și o funcție de anulare. Apelarea funcției de anulare anulează acest context și toate contextelor sale copil.
  • context.WithDeadline(parent Context, deadline time.Time) : Returnează un context copil care se anulează automat când timpul specificat este atins. De asemenea, returnează o funcție de anulare pentru anulare manuală.
  • context.WithTimeout(parent Context, timeout time.Duration) : La fel ca WithDeadline, dar cu o durată specificată.
  • context.WithValue(parent Context, key, val interface{}) : Returnează un context copil cu o valoare atribuită unei chei.

Aplicații:

  • Anularea operațiilor: De exemplu, timeout pentru o solicitare HTTP sau întreruperea unei operațiuni lungi.
  • Transmiterea datelor: De exemplu, ID-ul solicitării pentru jurnalizare, informații de autentificare.

Exemplu de utilizare a context.WithTimeout:

package main

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

func longRunningOperation(ctx context.Context, resultChan chan string) {
	select {
	case <-time.After(3 * time.Second):
		// Operațiunea s-a finalizat cu succes
		resultChan <- "Operațiune finalizată"
	case <-ctx.Done():
		// Contextul a fost anulat
		err := ctx.Err() // Obține motivul anulării
		resultChan <- fmt.Sprintf("Operațiune anulată: %v", err)
	}
}

func main() {
	// Crează un context cu timeout de 2 secunde
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // Asigură apelul funcției de anulare

	resultChan := make(chan string, 1)

	go longRunningOperation(ctx, resultChan)

	// Așteaptă rezultatul sau anularea
	select {
	case res := <-resultChan:
		fmt.Println(res)
	case <-ctx.Done():
		fmt.Printf("Contextul principal s-a terminat: %v\n", ctx.Err())
	}

	// Așteaptă puțin pentru ca goroutine-ul să se termine dacă a fost anulată
	time.Sleep(1 * time.Second)
}

În acest exemplu, longRunningOperation verifică dacă contextul a fost anulat. Dacă timeout-ul contextului principal (2 secunde) expiră înainte ca operațiunea (3 secunde) să se finalizeze, goroutine-ul primește semnalul de anulare prin ctx.Done() și se termină.