Menu
Coddy logo textTech

Istruzione select

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 62 di 107.

L'istruzione select consente a una goroutine di attendere contemporaneamente più operazioni sui canali. È simile a un'istruzione switch, ma ogni caso prevede un invio o una ricezione su un canale. Quando più canali sono pronti, select ne sceglie uno a caso.

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)
    }
}

Senza select, ricevere da ch1 bloccherebbe finché non arrivano dati, rischiando di perdere i dati su ch2. Con select, viene gestito per primo il canale che riceve i dati.

Il caso default rende select non bloccante. Viene eseguito immediatamente se nessun canale è pronto:

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

Uno schema comune combina select con i timeout usando time.After, che restituisce un canale che riceve un valore dopo la durata specificata:

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

Questo impedisce al tuo programma di attendere per sempre quando un'operazione sul canale potrebbe non completarsi mai.

challenge icon

Sfida

Facile

Creiamo un monitor di servizi che usa l’istruzione select per gestire più origini dati simultanee. Il monitor ascolterà contemporaneamente diversi canali di servizio e risponderà in modo appropriato quando arrivano dati o quando non sono disponibili aggiornamenti.

Organizzerai il codice in due file:

  • monitor.go: definisci la logica di monitoraggio dei servizi, gestendo i canali con select.

    Crea una struct ServiceUpdate con i campi Name (string) e Status (string).

    Implementa una funzione Monitor che accetta tre canali: primary chan ServiceUpdate, backup chan ServiceUpdate e done chan bool. Questa funzione deve usare select per ascoltare contemporaneamente tutti e tre i canali:

    • Quando riceve da primary: restituisce la stringa formattata Primary: [Name] is [Status]
    • Quando riceve da backup: restituisce la stringa formattata Backup: [Name] is [Status]
    • Quando riceve da done: restituisce Monitoring stopped

    Implementa una funzione CheckStatus che accetta un singolo updates chan ServiceUpdate e usa select con un caso default per eseguire un controllo non bloccante:

    • Se è disponibile un aggiornamento: restituisce Update available: [Name]
    • Se non è disponibile alcun aggiornamento (caso default): restituisce No updates pending
  • main.go: configura i canali e mostra il comportamento di select bloccante e non bloccante.

    Leggi dalla riga di input una modalità che determina quale scenario eseguire: primary, backup, stop o check.

    Per le modalità primary, backup e stop: leggi anche il nome e lo stato di un servizio. Crea i tre canali, avvia una goroutine che invia i dati al canale appropriato in base alla modalità, quindi chiama Monitor e stampa il risultato.

    Per la modalità check: leggi il nome e lo stato di un servizio, oltre a un flag (send o nosend) che indica se inviare i dati prima del controllo. Crea un canale con buffer e capacità 1. Se il flag è send, invia un aggiornamento al canale prima di chiamare CheckStatus. Stampa il risultato di CheckStatus.

Verranno forniti i seguenti input:

  • Riga 1: modalità (primary, backup, stop o check)
  • Riga 2: nome del servizio
  • Riga 3: stato del servizio
  • Riga 4 (solo per la modalità check): send o nosend

Ad esempio, dato:

primary
Database
healthy

L’output dovrebbe essere:

Primary: Database is healthy

E dato:

check
Cache
active
nosend

L’output dovrebbe essere:

No updates pending

Provalo tu

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: Gestire le diverse modalità: "primary", "backup", "stop", "check"
	
	// Per le modalità "primary", "backup", "stop":
	// - Crea tre canali: primary, backup, done
	// - Avvia una goroutine che invia i dati al canale appropriato
	// - Chiama Monitor e stampa il risultato
	
	// Per la modalità "check":
	// - Leggi il flag aggiuntivo ("send" o "nosend")
	// - Crea un canale con buffer di capacità 1
	// - Se il flag è "send", invia un aggiornamento al canale
	// - Chiama CheckStatus e stampa il risultato
	
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online