Sobes.tech
Junior

Cos'è il contesto in Go?

sobes.tech AI

Risposta dell'AI

Il contesto (context.Context) in Go è un oggetto che trasporta una scadenza, un segnale di cancellazione e dati specifici della richiesta. Viene utilizzato per gestire il ciclo di vita delle goroutine e per trasmettere informazioni tra di esse durante l'esecuzione di una richiesta/operazione.

Caratteristiche principali:

  • Sicuro per la concorrenza: Può essere trasferito in modo sicuro tra goroutine.
  • Immutabile: Una volta creato, un Context non può essere modificato. I contesti derivati vengono creati a partire da quello genitore.
  • Gerarchico: I contesti formano un albero con radice (context.Background() o context.TODO()). La cancellazione del contesto genitore porta alla cancellazione di tutti i figli.

Funzioni principali del pacchetto context:

  • context.Background() : Contesto vuoto, generalmente usato nella funzione main, nelle richieste di alto livello o durante i test. Non viene mai cancellato.
  • context.TODO() : Anch'esso un contesto vuoto. Usato come segnaposto quando non si sa quale contesto usare, o se la funzionalità del contesto non è ancora implementata.
  • context.WithCancel(parent Context) : Restituisce un nuovo contesto figlio e una funzione di cancellazione. Chiamando questa funzione si cancella questo contesto e tutti i suoi contesti figli.
  • context.WithDeadline(parent Context, deadline time.Time) : Restituisce un contesto figlio che si cancella automaticamente quando si raggiunge il tempo specificato. Restituisce anche una funzione di cancellazione per la cancellazione manuale.
  • context.WithTimeout(parent Context, timeout time.Duration) : Come WithDeadline, ma con una durata specificata.
  • context.WithValue(parent Context, key, val interface{}) : Restituisce un contesto figlio con un valore associato a una chiave.

Applicazioni:

  • Cancellazione di operazioni: Per esempio, un timeout di una richiesta HTTP o l'interruzione di un'operazione lunga.
  • Trasmissione di dati: Per esempio, ID di richiesta per il logging, informazioni di autenticazione.

Esempio di utilizzo di context.WithTimeout:

package main

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

func longRunningOperation(ctx context.Context, resultChan chan string) {
	select {
	case <-time.After(3 * time.Second):
		// Operazione completata con successo
		resultChan <- "Operazione completata"
	case <-ctx.Done():
		// Il contesto è stato cancellato
		err := ctx.Err() // Ottieni la causa della cancellazione
		resultChan <- fmt.Sprintf("Operazione cancellata: %v", err)
	}
}

func main() {
	// Crea un contesto con timeout di 2 secondi
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // Garantisce la chiamata di cancellazione

	resultChan := make(chan string, 1)

	go longRunningOperation(ctx, resultChan)

	// Attende il risultato o la cancellazione
	select {
	case res := <-resultChan:
		fmt.Println(res)
	case <-ctx.Done():
		fmt.Printf("Contesto principale terminato: %v\n", ctx.Err())
	}

	// Attende un po' per permettere alla goroutine di terminare se è stata cancellata
	time.Sleep(1 * time.Second)
}

In questo esempio, longRunningOperation verifica se il contesto è stato cancellato. Se il timeout del contesto principale (2 secondi) scade prima che l'operazione finisca (3 secondi), la goroutine riceve il segnale di cancellazione tramite ctx.Done() e termina.