Sentencia select en el lenguaje Go
Sentencias condicionales en el lenguaje Go
select es una estructura de control en Go, similar a la sentencia switch.
La sentencia select solo se puede usar para operaciones de canal; cada case debe ser una operación de canal, ya sea de envío o de recepción.
La sentencia select monitorea las operaciones en todos los canales especificados; tan pronto como uno de los canales esté listo, ejecuta el bloque de código correspondiente.
Si varios canales están listos, la sentencia select elegirá aleatoriamente un canal para ejecutar. Si ningún canal está listo, entonces se ejecuta el código del bloque default.
Sintaxis
La sintaxis de la sentencia select en el lenguaje de programación Go es la siguiente:
select {
case <- channel1:
// Código a ejecutar
case value := <- channel2:
// Código a ejecutar
case channel3 <- value:
// Código a ejecutar
// Puedes definir cualquier cantidad de case
default:
// Código a ejecutar cuando ningún canal está listo
}
Lo siguiente describe la sintaxis de la sentencia select:
- Cada case debe ser un canal
- Todas las expresiones channel serán evaluadas
- Todas las expresiones que se envían serán evaluadas
- Si cualquier canal puede ejecutarse, se ejecuta; los demás se ignoran.
- Si hay varios case que pueden ejecutarse, select elegirá uno al azar de manera justa para ejecutarlo; los otros no se ejecutarán.
De lo contrario:- Si hay una cláusula default, se ejecuta esa sentencia.
- Si no hay cláusula default, select se bloqueará hasta que algún canal pueda ejecutarse; Go no vuelve a evaluar los channel ni los valores.
Ejemplo
Demostración de la aplicación de la sentencia select:
Ejemplo
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
El resultado de ejecutar el código anterior es:
received one received two
En el ejemplo anterior, creamos dos canales, c1 y c2.
La sentencia select espera datos de los dos canales. Si recibe datos de c1, imprime "received one"; si recibe datos de c2, imprime "received two".
En el siguiente ejemplo, definimos dos canales e iniciamos dos goroutines para obtener datos de estos dos canales. En la función main, usamos la sentencia select para hacer una selección no bloqueante entre los dos canales; si ninguno de los dos canales tiene datos disponibles, se ejecuta la sentencia de la cláusula default.
Después de ejecutar el siguiente ejemplo, se obtendrán continuamente datos de los dos canales; cuando ninguno de los dos canales tenga datos disponibles, se mostrará "no message received".
Ejemplo
import "fmt"
func main() {
// Definir dos canales
ch1 := make(chan string)
ch2 := make(chan string)
// Iniciar dos goroutines para obtener datos de los dos canales respectivamente
go func() {
for {
ch1 <- "from 1"
}
}()
go func() {
for {
ch2 <- "from 2"
}
}()
// Usar la sentencia select para obtener datos de los dos canales de forma no bloqueante
for {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
default:
// Si ninguno de los dos canales tiene datos disponibles, ejecuta las sentencias de aquí
fmt.Println("no message received")
}
}
}