Sentencia select en el lenguaje Go

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:
    1. Si hay una cláusula default, se ejecuta esa sentencia.
    2. 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

package main

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

package main

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

Go 语言条件语句Sentencias condicionales en el lenguaje Go

Otras extensiones