Sobes.tech
Junior

¿Qué es el contexto en Go?

sobes.tech AI

Respuesta de la IA

El contexto (context.Context) en Go es un objeto que lleva un plazo límite, una señal de cancelación y datos específicos de la solicitud. Se usa para gestionar el ciclo de vida de las goroutines y para transmitir información entre ellas durante la ejecución de una solicitud/operación.

Características principales:

  • Seguro para concurrencia: Puede transferirse de forma segura entre goroutines.
  • Inmutable: Una vez creado, un Context no puede cambiarse. Los contextos derivados se crean a partir del padre.
  • Jerárquico: Los contextos forman un árbol con raíz (context.Background() o context.TODO()). La cancelación del contexto padre lleva a la cancelación de todos los hijos.

Funciones principales del paquete context:

  • context.Background(): Contexto vacío, generalmente usado en la función main, en solicitudes de alto nivel o en pruebas. Nunca se cancela.
  • context.TODO(): También un contexto vacío. Se usa como marcador de posición cuando no se sabe qué contexto usar, o si la funcionalidad del contexto aún no está implementada.
  • context.WithCancel(parent Context): Devuelve un nuevo contexto hijo y una función de cancelación. Llamar a la función de cancelación cancela este contexto y todos sus contextos hijos.
  • context.WithDeadline(parent Context, deadline time.Time): Devuelve un contexto hijo que se cancela automáticamente cuando llega la hora especificada. También devuelve una función de cancelación para cancelación manual.
  • context.WithTimeout(parent Context, timeout time.Duration): Igual que WithDeadline, pero especificando una duración.
  • context.WithValue(parent Context, key, val interface{}): Devuelve un contexto hijo con un valor asociado a una clave.

Aplicaciones:

  • Cancelar operaciones: Por ejemplo, un timeout en una solicitud HTTP o la interrupción de una operación prolongada.
  • Transmisión de datos: Por ejemplo, ID de solicitud para registro, información de autenticación.

Ejemplo de uso de context.WithTimeout:

package main

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

func longRunningOperation(ctx context.Context, resultChan chan string) {
	select {
	case <-time.After(3 * time.Second):
		// Operación completada con éxito
		resultChan <- "Operación completada"
	case <-ctx.Done():
		// El contexto fue cancelado
		err := ctx.Err() // Obtenemos la causa de la cancelación
		resultChan <- fmt.Sprintf("Operación cancelada: %v", err)
	}
}

func main() {
	// Crear un contexto con timeout de 2 segundos
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // Garantizar llamada a cancel

	resultChan := make(chan string, 1)

	go longRunningOperation(ctx, resultChan)

	// Esperar resultado o cancelación
	select {
	case res := <-resultChan:
		fmt.Println(res)
	case <-ctx.Done():
		fmt.Printf("Context principal terminado: %v\n", ctx.Err())
	}

	// Esperar un poco para que la goroutine termine si fue cancelada
	time.Sleep(1 * time.Second)
}

En este ejemplo, longRunningOperation verifica si el contexto fue cancelado. Si el timeout del contexto principal (2 segundos) expira antes de que la operación termine (3 segundos), la goroutine recibe la señal de cancelación a través de ctx.Done() y termina.