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.
- 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 <- .
- 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