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
Contextnon può essere modificato. I contesti derivati vengono creati a partire da quello genitore. - Gerarchico: I contesti formano un albero con radice (
context.Background()ocontext.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): ComeWithDeadline, 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.