Middle
Cuéntame sobre los casos de uso del contexto en Go.
sobes.tech AI
Respuesta de la IA
El contexto en Go se utiliza para gestionar el ciclo de vida de las solicitudes y controlar la ejecución de las goroutines. Los casos principales de uso:
- Cancelación: Permite cancelar la cadena de goroutines relacionada con una solicitud específica. Por ejemplo, al cerrar la conexión o por timeout.
- Timeout: Establece un plazo límite para la operación. Si la operación no termina en ese plazo, el contexto se cancela. Esto evita esperas infinitas.
- Transferencia de datos específicos de la solicitud: Permite pasar datos relacionados con una solicitud concreta (como ID de usuario, identificador de trazas) a través de la cadena de llamadas sin cambiar sus firmas.
Ejemplos de uso:
-
Cancelación por señal:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Trabajador %d interrumpido\n", id) return default: fmt.Printf("Trabajador %d trabajando...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Garantiza la cancelación go worker(ctx, 1) go worker(ctx, 2) time.Sleep(2 * time.Second) cancel() // Cancela el contexto time.Sleep(500 * time.Millisecond) // Da tiempo a que las goroutines terminen } -
Timeout:
package main import ( "context" "fmt" "time" ) func longOperation(ctx context.Context) error { select { case <-time.After(3 * time.Second): // Simulación de una operación larga fmt.Println("Operación completada con éxito") return nil case <-ctx.Done(): fmt.Println("Operación cancelada por el contexto:", ctx.Err()) return ctx.Err() } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() err := longOperation(ctx) if err != nil { fmt.Println("Error:", err) } } -
Transferencia de datos:
package main import ( "context" "fmt" ) type UserKey string const userIDKey UserKey = "userID" func processRequest(ctx context.Context) { userID := ctx.Value(userIDKey).(int) fmt.Printf("Procesando solicitud para el usuario ID: %d\n", userID) // Procesamiento adicional de la solicitud usando userID } func main() { ctx := context.WithValue(context.Background(), userIDKey, 123) processRequest(ctx) }
Es importante usar context.Background() o context.TODO() como contexto raíz y pasarlo hacia abajo en la cadena de llamadas. No se debe almacenar el contexto en estructuras de datos si no está directamente relacionado con el ciclo de vida de esa estructura.