Menu
Coddy logo textTech

Instrukcja select

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 62 z 107.

Instrukcja select pozwala gorutynie jednocześnie czekać na wiele operacji na kanałach. Przypomina instrukcję switch, ale każdy przypadek obejmuje wysłanie do kanału lub odbiór z kanału. Gdy kilka kanałów jest gotowych, select wybiera jeden losowo.

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

Bez select odbieranie z ch1 blokowałoby działanie do momentu nadejścia danych, co mogłoby spowodować pominięcie danych z ch2. Dzięki select obsługiwany jest kanał, który jako pierwszy otrzyma dane.

Przypadek default sprawia, że select nie blokuje działania. Wykonuje się natychmiast, jeśli żaden kanał nie jest gotowy:

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

Typowy wzorzec łączy select z limitami czasu za pomocą time.After, które zwraca kanał odbierający wartość po określonym czasie:

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

Zapobiega to bezterminowemu oczekiwaniu programu, gdy operacja na kanale może nigdy się nie zakończyć.

challenge icon

Wyzwanie

Łatwy

Zbudujmy monitor usług, który używa instrukcji select do obsługi wielu współbieżnych źródeł danych. Monitor będzie jednocześnie nasłuchiwać różnych kanałów usług i odpowiednio reagować, gdy nadejdą dane lub gdy nie będą dostępne żadne aktualizacje.

Rozmieścisz swój kod w dwóch plikach:

  • monitor.go: Zdefiniuj logikę monitorowania usług z obsługą kanałów opartą na select.

    Utwórz strukturę ServiceUpdate z polami Name (string) i Status (string).

    Zaimplementuj funkcję Monitor, która przyjmuje trzy kanały: primary chan ServiceUpdate, backup chan ServiceUpdate i done chan bool. Funkcja powinna używać select, aby jednocześnie nasłuchiwać na wszystkich trzech kanałach:

    • Gdy odbierze dane z primary: zwróć sformatowany tekst Primary: [Name] is [Status]
    • Gdy odbierze dane z backup: zwróć sformatowany tekst Backup: [Name] is [Status]
    • Gdy odbierze dane z done: zwróć Monitoring stopped

    Zaimplementuj funkcję CheckStatus, która przyjmuje jeden kanał updates chan ServiceUpdate i używa select z przypadkiem default, aby wykonać nieblokujące sprawdzenie:

    • Jeśli aktualizacja jest dostępna: zwróć Update available: [Name]
    • Jeśli aktualizacja nie jest dostępna (przypadek default): zwróć No updates pending
  • main.go: Skonfiguruj kanały i pokaż działanie blokującego i nieblokującego select.

    Odczytaj z wejścia tryb, który określa, który scenariusz uruchomić: primary, backup, stop lub check.

    W trybach primary, backup i stop: odczytaj także nazwę i status usługi. Utwórz trzy kanały, uruchom gorutynę, która wysyła dane do odpowiedniego kanału na podstawie trybu, a następnie wywołaj Monitor i wyświetl jego wynik.

    W trybie check: odczytaj nazwę i status usługi oraz flagę (send lub nosend) wskazującą, czy przed sprawdzeniem wysłać dane. Utwórz buforowany kanał o pojemności 1. Jeśli flaga ma wartość send, wyślij aktualizację do kanału przed wywołaniem CheckStatus. Wyświetl wynik funkcji CheckStatus.

Zostaną podane następujące dane wejściowe:

  • Linia 1: tryb (primary, backup, stop lub check)
  • Linia 2: nazwa usługi
  • Linia 3: status usługi
  • Linia 4 (tylko dla trybu check): send lub nosend

Na przykład dla danych:

primary
Database
healthy

Wynik powinien wyglądać następująco:

Primary: Database is healthy

A dla danych:

check
Cache
active
nosend

Wynik powinien wyglądać następująco:

No updates pending

Spróbuj swoich sił

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: Obsłuż różne tryby: "primary", "backup", "stop", "check"
	
	// Dla trybów "primary", "backup", "stop":
	// - Utwórz trzy kanały: primary, backup, done
	// - Uruchom gorutynę, która wysyła dane do odpowiedniego kanału
	// - Wywołaj Monitor i wypisz wynik
	
	// Dla trybu "check":
	// - Odczytaj dodatkową flagę ("send" lub "nosend")
	// - Utwórz kanał buforowany o pojemności 1
	// - Jeśli flaga to "send", wyślij aktualizację do kanału
	// - Wywołaj CheckStatus i wypisz wynik
	
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online