Canal en Golang

En lenguaje Go, un canal es un medio a través del cual una gorutina se comunica con otra gorutina y esta comunicación no tiene bloqueos. O dicho de otro modo, un canal es una técnica que permite que una gorutina envíe datos a otra gorutina. Por defecto, el canal es bidireccional, lo que significa que las rutinas pueden enviar o recibir datos a través del mismo canal, como se muestra en la siguiente imagen:

Crear un canal

En el lenguaje Go, un canal se crea usando la palabra clave chan y solo puede transferir datos del mismo tipo, no se permite el transporte de diferentes tipos de datos desde el mismo canal.

Sintaxis:

var Channel_name chan Type

También puede crear un canal usando la función make() usando una declaración abreviada.

Sintaxis:

channel_name:= make(chan Type)

Ejemplo:

// Go program to illustrate
// how to create a channel
package main
  
import "fmt"
  
func main() {
  
    // Creating a channel
    // Using var keyword
    var mychannel chan int
    fmt.Println("Value of the channel: ", mychannel)
    fmt.Printf("Type of the channel: %T ", mychannel)
  
    // Creating a channel using make() function
    mychannel1 := make(chan int)
    fmt.Println("\nValue of the channel1: ", mychannel1)
    fmt.Printf("Type of the channel1: %T ", mychannel1)
}

Producción:

Value of the channel:  
Type of the channel: chan int 
Value of the channel1:  0x432080
Type of the channel1: chan int 

Enviar y recibir datos de un canal

En el lenguaje Go, el canal funciona con dos operaciones principales, una es enviar y otra es recibir, ambas operaciones conocidas colectivamente como comunicación. Y la dirección del operador <- indica si los datos se reciben o se envían. En el canal, la operación de envío y recepción se bloquea hasta que otro lado no esté listo por defecto. Permite que goroutine se sincronice entre sí sin bloqueos explícitos o variables de condición.

  1. Operación de envío: la operación de envío se utiliza para enviar datos de una rutina a otra con la ayuda de un canal. Valores como int, float64 y bool pueden enviarse de forma segura y fácil a través de un canal porque se copian, por lo que no hay riesgo de acceso simultáneo accidental del mismo valor. Del mismo modo, las strings también son seguras para transferir porque son inmutables. Pero el envío de punteros o referencias como un segmento, un mapa, etc. a través de un canal no es seguro porque el valor de los punteros o la referencia puede cambiar al enviar goroutine o al recibir goroutine al mismo tiempo y el resultado es impredecible. Por lo tanto, cuando use punteros o referencias en el canal, debe asegurarse de que solo puedan acceder por una gorutina a la vez.
    Mychannel <- element

    La declaración anterior indica que los datos (elemento) se envían al canal (Mychannel) con la ayuda de un operador <- .

  2. Operación de recepción: La operación de recepción se utiliza para recibir los datos enviados por el operador de envío.
    element := <-Mychannel

    La declaración anterior indica que el elemento recibe datos del canal (Mychannel). Si el resultado de la declaración recibida no se va a utilizar también es una declaración válida. También puede escribir una instrucción de recepción como:

    <-Mychannel

Ejemplo:

// Go program to illustrate send
// and receive operation
package main
  
import "fmt"
  
func myfunc(ch chan int) {
  
    fmt.Println(234 + <-ch)
}
func main() {
    fmt.Println("start Main method")
    // Creating a channel
    ch := make(chan int)
  
    go myfunc(ch)
    ch <- 23
    fmt.Println("End Main method")
}

Producción:

start Main method
257
End Main method

Cerrar un canal

También puede cerrar un canal con la ayuda de la función close(). Esta es una función incorporada y establece una bandera que indica que no se enviará más valor a este canal.

Sintaxis:

close()

También puede cerrar el canal usando for range loop. Aquí, la rutina del receptor puede verificar que el canal esté abierto o cerrado con la ayuda de la sintaxis dada:

ele, ok:= <- Mychannel

Aquí, si el valor de ok es verdadero, lo que significa que el canal está abierto, se pueden realizar operaciones de lectura. Y si el valor de es falso, lo que significa que el canal está cerrado, las operaciones de lectura no se realizarán.

Ejemplo:

// Go program to illustrate how
// to close a channel using for
// range loop and close function
package main
  
import "fmt"
  
// Function
func myfun(mychnl chan string) {
  
    for v := 0; v < 4; v++ {
        mychnl <- "GeeksforGeeks"
    }
    close(mychnl)
}
  
// Main function
func main() {
  
    // Creating a channel
    c := make(chan string)
  
    // calling Goroutine
    go myfun(c)
  
    // When the value of ok is
    // set to true means the
    // channel is open and it
    // can send or receive data
    // When the value of ok is set to
    // false means the channel is closed
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("Channel Close ", ok)
            break
        }
        fmt.Println("Channel Open ", res, ok)
    }
}

Producción:

Channel Open  GeeksforGeeks true
Channel Open  GeeksforGeeks true
Channel Open  GeeksforGeeks true
Channel Open  GeeksforGeeks true
Channel Close  false

Puntos importantes

  • Bloqueo de envío y recepción: en el canal, cuando los datos se envían a un canal, el control se bloquea en esa declaración de envío hasta que otra gorutina lea desde ese canal. De manera similar, cuando un canal recibe datos de la goroutine, la declaración de lectura se bloquea hasta otra declaración de la goroutine.
  • Canal de valor cero: el valor cero del canal es cero.
  • Bucle for en el canal: un bucle for puede iterar sobre los valores secuenciales enviados en el canal hasta que se cierre.

    Sintaxis:

    for item := range Chnl { 
         // statements..
    }
    

    Ejemplo:

    // Go program to illustrate how to
    // use for loop in the channel
      
    package main
      
    import "fmt"
      
    // Main function
    func main() {
      
        // Creating a channel
        // Using make() function
        mychnl := make(chan string)
      
        // Anonymous goroutine
        go func() {
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "GeeksforGeeks"
            close(mychnl)
        }()
      
        // Using for loop
        for res := range mychnl {
            fmt.Println(res)
        }
    }

    Producción:

    GFG
    gfg
    Geeks
    GeeksforGeeks
    
    
  • Longitud del canal: en el canal, puede encontrar la longitud del canal usando la función len() . Aquí, la longitud indica el número de valores en cola en el búfer del canal.

    Ejemplo:

    // Go program to illustrate how to
    // find the length of the channel
      
    package main
      
    import "fmt"
    a
    // Main function
    func main() {
      
        // Creating a channel
        // Using make() function
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "GeeksforGeeks"
      
        // Finding the length of the channel
        // Using len() function
        fmt.Println("Length of the channel is: ", len(mychnl))
    }

    Producción:

    Length of the channel is:  4
  • Capacidad del canal: en el canal, puede encontrar la capacidad del canal usando la función cap(). Aquí, la capacidad indica el tamaño del búfer.

    Ejemplo:

    // Go program to illustrate how to
    // find the capacity of the channel
      
    package main
      
    import "fmt"
      
    // Main function
    func main() {
      
        // Creating a channel
        // Using make() function
        mychnl := make(chan string, 5)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "GeeksforGeeks"
      
        // Finding the capacity of the channel
        // Using cap() function
        fmt.Println("Capacity of the channel is: ", cap(mychnl))
    }

    Producción:

    Capacity of the channel is:  5
  • Selección y declaración de caso en el canal: en el lenguaje go, la declaración de selección es como una declaración de cambio sin ningún parámetro de entrada. Esta declaración de selección se usa en el canal para realizar una sola operación de varias operaciones proporcionadas por el bloque de casos.

Publicación traducida automáticamente

Artículo escrito por ankita_saini y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *