L'instrucció select en Go és una característica poderosa que permet esperar múltiples operacions de canal. És similar a una instrucció switch, però per a canals. Amb select, pots esperar que un o més canals estiguin llestos per enviar o rebre dades, i executar el codi corresponent quan això succeeixi.

Conceptes Clau

  • Canals: Els canals són utilitzats per comunicar-se entre goroutines. Pots enviar i rebre valors a través dels canals.
  • Goroutines: Les goroutines són funcions o mètodes que s'executen de manera concurrent amb altres goroutines.
  • Instrucció Select: Permet esperar múltiples operacions de canal i executar el codi corresponent quan una d'aquestes operacions està llesta.

Sintaxi de l'Instrucció Select

La sintaxi bàsica de l'instrucció select és la següent:

select {
case <-canal1:
    // codi a executar quan canal1 està llest per rebre
case valor := <-canal2:
    // codi a executar quan canal2 està llest per enviar
case canal3 <- valor:
    // codi a executar quan canal3 està llest per rebre un valor
default:
    // codi a executar si cap dels canals està llest
}

Exemple Pràctic

Vegem un exemple pràctic per entendre millor com funciona l'instrucció select.

Exemple: Temporitzador i Canal de Missatges

En aquest exemple, crearem un temporitzador i un canal de missatges. Utilitzarem l'instrucció select per esperar que un dels dos canals estigui llest.

package main

import (
    "fmt"
    "time"
)

func main() {
    messages := make(chan string)
    timer := time.After(2 * time.Second)

    go func() {
        time.Sleep(1 * time.Second)
        messages <- "Hola, món!"
    }()

    select {
    case msg := <-messages:
        fmt.Println("Missatge rebut:", msg)
    case <-timer:
        fmt.Println("Temps esgotat!")
    }
}

Explicació del Codi

  1. Creació de Canals:

    messages := make(chan string)
    timer := time.After(2 * time.Second)
    
    • messages: Un canal de tipus string per enviar missatges.
    • timer: Un canal que rebrà un valor després de 2 segons.
  2. Goroutine:

    go func() {
        time.Sleep(1 * time.Second)
        messages <- "Hola, món!"
    }()
    
    • Aquesta goroutine espera 1 segon i després envia el missatge "Hola, món!" al canal messages.
  3. Instrucció Select:

    select {
    case msg := <-messages:
        fmt.Println("Missatge rebut:", msg)
    case <-timer:
        fmt.Println("Temps esgotat!")
    }
    
    • Si el canal messages està llest per enviar un missatge, es llegeix el missatge i es mostra.
    • Si el temporitzador expira abans que arribi el missatge, es mostra "Temps esgotat!".

Exercicis Pràctics

Exercici 1: Canal de Comptador

Crea un programa que utilitzi un canal per comptar fins a 5. Utilitza una goroutine per enviar els números al canal i una instrucció select per rebre'ls i imprimir-los.

Solució

package main

import (
    "fmt"
    "time"
)

func main() {
    counter := make(chan int)

    go func() {
        for i := 1; i <= 5; i++ {
            counter <- i
            time.Sleep(500 * time.Millisecond)
        }
        close(counter)
    }()

    for {
        select {
        case num, ok := <-counter:
            if !ok {
                fmt.Println("Comptador tancat")
                return
            }
            fmt.Println("Número rebut:", num)
        }
    }
}

Exercici 2: Canal de Temps i Missatges

Crea un programa que utilitzi dos canals: un per enviar missatges i un altre per enviar el temps actual cada segon. Utilitza una instrucció select per imprimir el missatge o el temps, segons quin canal estigui llest primer.

Solució

package main

import (
    "fmt"
    "time"
)

func main() {
    messages := make(chan string)
    ticker := time.NewTicker(1 * time.Second)

    go func() {
        for {
            time.Sleep(3 * time.Second)
            messages <- "Missatge periòdic"
        }
    }()

    for {
        select {
        case msg := <-messages:
            fmt.Println("Missatge rebut:", msg)
        case t := <-ticker.C:
            fmt.Println("Hora actual:", t)
        }
    }
}

Conclusió

L'instrucció select és una eina essencial per gestionar la concurrència en Go. Permet esperar múltiples operacions de canal i executar el codi corresponent quan una d'aquestes operacions està llesta. Amb la pràctica, podràs utilitzar select per crear programes més eficients i responsius.

En el següent tema, explorarem els mutexes i la sincronització per gestionar l'accés concurrent a recursos compartits.

© Copyright 2024. Tots els drets reservats