馃敟 Uso de select para el manejo de m煤ltiples canales

鈽 驴C贸mo manejar m煤ltiples canales en Go?

Supongamos que tenemos m煤ltiples m煤ltiples rutinas, y deseamos capturar cual de ellas es la primera en responder. Para dicho caso podemos utilizar un canal para cada una de ellas, en combinaci贸n con select que haga referencia a cada uno de los canales.

Supongamos que estamos en una hip贸dromo, y cada uno de los caballos representa una funci贸n. Cada funci贸n esta asignada en este caso a una rutina, pues los caballos corren todos al mismo tiempo, pero solo deseamos saber cual es el primero en llegar.

package main

import (
    "fmt"
    "time"
)

func caballo1(can chan string) {
    time.Sleep(time.Second * 3)
    can <- "Caballo 1 completo la carrera"
}

func caballo2(can chan string) {
    time.Sleep(time.Second * 2)
    can <- "Caballo 2 completo la carrera"
}

func caballo3(can chan string) {
    time.Sleep(time.Second * 4)
    can <- "Caballo 3 completo la carrera"
}

func main() {
    can1 := make(chan string)
    can2 := make(chan string)
    can3 := make(chan string)

    go caballo1(can1)
    go caballo2(can2)
    go caballo3(can3)

    select {
    case ganador := <-can1:
        fmt.Println(ganador)
    case ganador := <-can2:
        fmt.Println(ganador)
    case ganador := <-can2:
        fmt.Println(ganador)
    }
}

Primero recreamos 3 funciones que reciben un canal como argumento, y escriben un string sobre este.

func caballo1(can chan string) {
    time.Sleep(time.Second * 3)
    can <- "Caballo 1 completo la carrera"
}

func caballo2(can chan string) {
    time.Sleep(time.Second * 2)
    can <- "Caballo 2 completo la carrera"
}

func caballo3(can chan string) {
    time.Sleep(time.Second * 4)
    can <- "Caballo 3 completo la carrera"
}

Dentro de la funci贸n main creamos tres canales, cada uno de ellos ser谩 utilizado para cada uno de los par谩metros de cada funci贸n.

can1 := make(chan string)
can2 := make(chan string)
can3 := make(chan string)

Para realizar la ejecuci贸n de las tres funcionen en paralelo, a cada una la alojamos en una rutina.

go caballo1(can1)
go caballo2(can2)
go caballo3(can3)

Finalmente podemos utilizar un select para asociar cada posible canal, el primero que retorne una salida sera el que imprimamos.

select {
    case ganador := <-can1:
        fmt.Println(ganador)
    case ganador := <-can2:
        fmt.Println(ganador)
    case ganador := <-can2:
        fmt.Println(ganador)
}

En este caso, como el caballo que tarda menos tiempo en completar la carrera es el caballo 2, nuestra salida es.

Caballo 2 completo la carrera