English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Golang

Sentencias de control de Golang

Funciones y métodos de Golang

Estructuras de Golang

Cortes y arreglos de Golang

Cadenas (String) de Golang

Punteros de Golang

Interfaces de Golang

Concurrencia de Golang

Excepciones (Error) de Golang

Misceláneos de Golang

Canal (Channel) del lenguaje Go

En el lenguaje Go, el canal es el medio de comunicación entre goroutine y otro goroutine, y esta comunicación es sin bloqueo. En otras palabras, el canal es una técnica que permite a un goroutine enviar datos a otro goroutine. Por defecto, el canal es bidireccional, lo que significa que un goroutine puede enviar o recibir datos a través del mismo canal, como se muestra en la siguiente figura:

创建通道

En el lenguaje Go, se crea un canal utilizando la palabra clave chan, y el canal solo puede transmitir datos del mismo tipo, no se permite transmitir diferentes tipos de datos a través del mismo canal.

Sintaxis:

var Channel_name chan Type

También se puede usar una declaración abreviada para crear un canal a través de la función make().

Sintaxis:

channel_name:= make(chan Type)
package main
import "fmt"
func main() {
    //Se crea un canal utilizando la palabra clave var
    var mychannel chan int
    fmt.Println("channel的值: ", mychannel)
    fmt.Printf("channel的类型: %T ", mychannel)
    // Usar la función make() para crear un canal
    mychannel1 := make(chan int)
    fmt.Println("\nchannel1El valor: ", mychannel1)
    fmt.Printf("channel1El tipo: %T "1)
{}

Salida:

El valor del canal: <nil>
El tipo del canal: chan int
Canales1El valor: 0xc0000160c0
Canales1El tipo: chan int

Enviar y recibir datos desde el canal

En el lenguaje Go, el trabajo de los canales tiene dos operaciones principales, una es enviar y la otra es recibir, estas dos operaciones se denominan en conjunto comunicación.-La dirección del operador indica si se está recibiendo o enviando datos. En los canales, por defecto, las operaciones de envío y recepción se bloquean hasta que el otro extremo no tenga datos. Esto permite que las goroutines se sincronicen entre sí sin locks 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 goroutine a otra a través de canales. Como int, float64Los valores como bool pueden enviarse de manera segura y fácil a través de canales, ya que se copian, por lo que no existe el riesgo de acceso concurrente a valores iguales. Del mismo modo, las cadenas de caracteres también son seguras, ya que son inmutables. Sin embargo, no es seguro enviar punteros o referencias (por ejemplo, cortes, conjuntos de mapas, etc.) a través de canales, ya que los valores de los punteros o referencias pueden cambiar a través de goroutines que envían o reciben simultáneamente, y los resultados son impredecibles. Por lo tanto, al usar punteros o referencias en canales, debe asegurarse de que solo puedan ser accedidos por una sola goroutine a la vez.

    Mychannel <- element

    上面的语句表明数据(element)在<-运算符的帮助下发送到通道(Mychannel)。

  2. 接收操作:接收操作用于接收发送操作方发送的数据。

    element := <-Mychannel

    上面的语句表明该元素从channel(Mychannel)接收数据。如果接收到的语句的结果不可用(不需要使用),则也是有效的语句。您还可以编写如下的receive语句:

    <-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
{} 
func main() { 
    fmt.Println("主方法开始") 
    //创建通道l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("主方法结束") 
{}

Salida:

主方法开始
257
主方法结束

关闭通道

您也可以在close()函数的帮助下关闭通道。这是一个内置函数,并设置一个标识,表示不再有任何值将发送到该通道。

Sintaxis:

close()

您也可以使用for范围循环关闭通道。在这里,接收器goroutine可以借助给定的语法检查通道是打开还是关闭:

ele, ok := <- Mychannel

在此,如果ok的值为true,则表示通道已打开,因此可以执行读取操作。并且,如果的值为false,则表示该通道已关闭,因此将不执行读取操作。

//Go程序说明如何
//关闭使用的通道
//range循环和关闭函数
package main
import "fmt"
func myfun(mychnl chan string) {
    for v := 0; v < 4; v++ {
        mychnl <- "w3codebox
    {}
    close(mychnl)
{}
func main() {
    //创建通道
    c := make(chan string)
    // 使用 Goroutine
    go myfun(c)
    //当ok的值为为true时,表示通道已打开,可以发送或接收数据
    //当ok的值设置为false时,表示通道已关闭
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("Cierre del canal ", ok)
            break
        {}
        fmt.Println("Canal abierto ", res, ok)
    {}
{}

Salida:

Canal abierto w3codebox true
Canal abierto w3codebox true
Canal abierto w3codebox true
Canal abierto w3codebox true
Cierre del canal false

Notas importantes

  • Bloquear envío y recepción:En el canal, cuando se envía datos al canal, el control se bloquea en la sentencia de envío hasta que otro goroutine lea datos del canal. De manera similar, cuando el canal recibe datos de un goroutine, la sentencia de lectura se bloquea hasta que otra sentencia de goroutine lo lea.

  • Canal de valor cero: Canalel valor cero es nil.

  • Bucle for en el canal: El bucle for puede recorrer los valores ordenados enviados en el canal hasta que se cierre.

    Sintaxis:

    for item := range Chnl { 
         // expresión...
    {}
    package main 
    import "fmt"
      
    func main() { 
      
        // Usar la función make() para crear un canal
        mychnl := make(chan string) 
      
        // Goroutine anónima 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "w3codebox
            close(mychnl) 
        }() 
      
        //Usar el bucle for
        for res := range mychnl { 
            fmt.Println(res) 
        {} 
    {}

    Salida:

    GFG
    gfg
    Geeks
    w3codebox
  • Longitud del canal:En el canal, puedes usarFunción len()Encontrar la longitud del canal. Aquí, la longitud representa la cantidad de valores en cola en el buffer del canal.

    package main 
      
    import "fmt"
    func main() { 
      
        // Usar la función make() para crear un canal 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Usar la función len() para encontrar la longitud del canal 
        fmt.Println("La longitud del canal es: ", len(mychnl)) 
    {}

    Salida:

    La longitud del canal es:  4
  • Capacidad del canal:En el canal, puedes usar la función cap() para encontrar la capacidad del canal. Aquí, la capacidad representa el tamaño del buffer.

    package main
    import "fmt"
    func main() {
        // Usar la función make() para crear un canal
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Usar la función cap() para encontrar la capacidad del canal
        fmt.Println("La capacidad del canal es: ", cap(mychnl))
    {}

    Salida:

    La capacidad del canal es:  5
  • Select y la sentencia case en el canal:En el lenguaje Go, la sentencia select es similar a una sentencia switch sin parámetros de entrada. Al usar la sentencia select en los canales, se ejecuta una sola operación de entre las múltiples proporcionadas por los bloques case.