Menu
Coddy logo textTech

Sentencia Select

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 62 de 107.

La instrucción select permite que una goroutine espere simultáneamente varias operaciones de canal. Es como una instrucción switch, pero cada caso implica un envío o una recepción por un canal. Cuando varios canales están listos, select elige uno al azar.

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    
    go func() { ch1 <- "from channel 1" }()
    go func() { ch2 <- "from channel 2" }()
    
    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    case msg2 := <-ch2:
        fmt.Println(msg2)
    }
}

Sin select, recibir de ch1 se bloquearía hasta que llegaran datos, lo que podría hacer que se perdieran datos en ch2. Con select, se gestiona el canal que recibe datos primero.

El caso default hace que select no sea bloqueante. Se ejecuta inmediatamente si ningún canal está listo:

select {
case msg := <-messages:
    fmt.Println("Received:", msg)
default:
    fmt.Println("No message available")
}

Un patrón común combina select con tiempos de espera mediante time.After, que devuelve un canal que recibe un valor después de la duración especificada:

select {
case result := <-ch:
    fmt.Println("Got result:", result)
case <-time.After(2 * time.Second):
    fmt.Println("Timeout!")
}

Esto evita que tu programa espere para siempre cuando una operación de canal podría no completarse nunca.

challenge icon

Desafío

Fácil

Construyamos un monitor de servicios que use la instrucción select para gestionar múltiples fuentes de datos concurrentes. Tu monitor escuchará simultáneamente diferentes canales de servicio y responderá adecuadamente cuando lleguen datos o cuando no haya actualizaciones disponibles.

Organizarás tu código en dos archivos:

  • monitor.go: Define la lógica de monitorización de servicios con gestión de canales basada en select.

    Crea una estructura ServiceUpdate con campos Name (string) y Status (string).

    Implementa una función Monitor que reciba tres canales: primary chan ServiceUpdate, backup chan ServiceUpdate y done chan bool. Esta función debe usar select para escuchar simultáneamente en los tres canales:

    • Al recibir de primary: devuelve la cadena formateada Primary: [Name] is [Status]
    • Al recibir de backup: devuelve la cadena formateada Backup: [Name] is [Status]
    • Al recibir de done: devuelve Monitoring stopped

    Implementa una función CheckStatus que reciba un único updates chan ServiceUpdate y use select con un caso default para realizar una comprobación no bloqueante:

    • Si hay una actualización disponible: devuelve Update available: [Name]
    • Si no hay ninguna actualización disponible (caso predeterminado): devuelve No updates pending
  • main.go: Configura los canales y muestra el comportamiento de select bloqueante y no bloqueante.

    Lee un modo de la entrada que determine qué escenario ejecutar: primary, backup, stop o check.

    Para los modos primary, backup y stop: lee también un nombre y un estado de servicio. Crea los tres canales, inicia una goroutine que envíe datos al canal correspondiente según el modo, después llama a Monitor e imprime su resultado.

    Para el modo check: lee un nombre y un estado de servicio, además de una marca (send o nosend) que indique si se deben enviar datos antes de realizar la comprobación. Crea un canal con búfer y capacidad 1. Si la marca es send, envía una actualización al canal antes de llamar a CheckStatus. Imprime el resultado de CheckStatus.

Se proporcionarán las siguientes entradas:

  • Línea 1: Modo (primary, backup, stop o check)
  • Línea 2: Nombre del servicio
  • Línea 3: Estado del servicio
  • Línea 4 (solo para el modo check): send o nosend

Por ejemplo, dada la siguiente entrada:

primary
Database
healthy

Tu salida debería ser:

Primary: Database is healthy

Y dada la siguiente entrada:

check
Cache
active
nosend

Tu salida debería ser:

No updates pending
FORMATO DE SALIDA REQUERIDO: [Tu contenido traducido aquí]

Pruébalo tú mismo

package main

import (
	"fmt"
)

func main() {
	var mode string
	fmt.Scanln(&mode)

	var serviceName string
	fmt.Scanln(&serviceName)

	var serviceStatus string
	fmt.Scanln(&serviceStatus)

	// TODO: Maneja diferentes modos: "primary", "backup", "stop", "check"
	
	// Para los modos "primary", "backup", "stop":
	// - Crea tres canales: primary, backup, done
	// - Lanza una goroutine que envía datos al canal apropiado
	// - Llama a Monitor e imprime el resultado
	
	// Para el modo "check":
	// - Lee el flag adicional ("send" o "nosend")
	// - Crea un canal con buffer de capacidad 1
	// - Si el flag es "send", envía una actualización al canal
	// - Llama a CheckStatus e imprime el resultado
	
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Go online