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

Golang basic tutorial

Golang control statements

Golang functions & methods

Golang structures

Golang slices & arrays

Golang strings (String)

Golang pointers

Golang interfaces

Golang concurrency

Golang exceptions (Error)

Golang other items

Canal (Channel) do Linguagem Go

No Go language, channels are the medium for communication between goroutines, and this communication is lock-free. In other words, a channel is a technology that allows one goroutine to send data to another goroutine. By default, channels are bidirectional, which means goroutines can send or receive data through the same channel, as shown in the following figure:

Criar canal

No idioma Go, usar a palavra-chave chan para criar canais, e esses canais podem transmitir apenas dados do mesmo tipo, não permitindo que dados de diferentes tipos sejam transmitidos pelo mesmo canal.

Sintaxe:

var Channel_name chan Type

Você também pode usar declarações abreviadas para criar canais através da função make().

Sintaxe:

channel_name:= make(chan Type)
package main
import "fmt"
func main() {
    //Usar a palavra-chave var para criar um canal
    var mychannel chan int
    fmt.Println("o valor do canal: ", mychannel)
    fmt.Printf("o tipo do canal: %T ", mychannel)
    // Usar a função make() para criar um canal
    mychannel1 := make(chan int)
    fmt.Println("\ncanal1o valor:1)
    fmt.Printf("canal1o tipo: %T "1)
}

Saída:

o valor do canal: <nil>
o tipo do canal: chan int
canal1o valor: 0xc0000160c0
canal1do tipo: chan int

Enviar e receber dados do canal

No idioma Go, o trabalho com canais tem duas operações principais: uma é o envio e a outra é a recebimento, essas duas operações são coletivamente chamadas de comunicação.-A direção do operador indica se é para receber ou enviar dados. No canal, por padrão, as operações de envio e recebimento bloqueiam até que o outro extremo não tenha mais dados. Isso permite que as goroutines se sincronizem umas com as outras sem locks explícitos ou variáveis de condição.

  1. Operação de envio:As operações de envio são usadas para enviar dados de uma goroutine para outra através de canais. Como int, float64Os valores como bool e outros podem ser enviados com segurança e facilidade através de canais, pois são copiados, portanto, não há risco de acesso concorrente acidental ao mesmo valor. Da mesma forma, as strings são seguras, pois são imutáveis. No entanto, enviar ponteiros ou referências (por exemplo, fatias, conjuntos map) através de canais não é seguro, pois os valores desses ponteiros ou referências podem ser alterados por goroutines que enviam ou recebem ao mesmo tempo, resultando em um resultado imprevisível. Portanto, ao usar ponteiros ou referências em canais, deve-se assegurar que eles sejam acessados por apenas uma goroutine por vez.

    Mycannel <- elemento

    A frase acima indica que os dados (elemento) foram<-com a ajuda do operador de envio para o canal (Mycannel).

  2. Operação de recebimento:A operação de recebimento é usada para receber os dados enviados pelo remetente da operação de envio.

    elemento := <-Mycannel

    A frase acima indica que o elemento foi recebido do canal (Mycannel). Se o resultado da frase recebida não estiver disponível (não necessário usar), também é uma frase válida. Você também pode escrever a seguinte frase de recebimento:

    <-Mycannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println("Método principal iniciado") 
    //Criar canal l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("Método principal finalizado") 
}

Saída:

Método principal iniciado
257
Método principal finalizado

Fechamento do canal

Você também pode fechar o canal com a ajuda da função close(). Esta é uma função built-in que define um sinal de que não haverá mais valores a serem enviados para o canal.

Sintaxe:

close()

Você também pode usar o loop de faixa for para fechar o canal. Aqui, o goroutine receptor pode usar a sintaxe fornecida para verificar se o canal está aberto ou fechado:

ele, ok := <- Mycannel

Aqui, se o valor de ok for true, significa que o canal foi aberto, portanto, pode ser executada a operação de leitura. E, se o valor for false, significa que o canal já foi fechado, portanto, a operação de leitura não será executada.

//A explicação do programa Go como
//Fechamento do canal usado
//loop de range e função de fechamento
package main
import "fmt"
func myfun(mychnl chan string) {
    for v := 0; v < 4; v++ {
        mychnl <- "w3codebox
    }
    close(mychnl)
}
func main() {
    //Criar canal
    c := make(chan string)
    // Uso de Goroutine
    go myfun(c)
    //Quando o valor de ok é true, significa que o canal foi aberto, permitindo o envio ou recebimento de dados
    //Quando o valor de ok é configurado como false, significa que o canal foi fechado
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("Fechamento do canal: ", ok)
            break
        }
        fmt.Println("Abertura do canal: ", res, ok)
    }
}

Saída:

Abertura do canal: w3codebox: true
Abertura do canal: w3codebox: true
Abertura do canal: w3codebox: true
Abertura do canal: w3codebox: true
Fechamento do canal: false

Atenção importante

  • Bloqueio de envio e recebimento:No canal, quando dados são enviados para o canal, o controle é bloqueado na instrução de envio até que outro goroutine leia os dados do canal. Da mesma forma, quando o canal recebe dados de um goroutine, a instrução de leitura é bloqueada até que outra instrução de goroutine seja executada.

  • Canal com zero valor: Canalo valor zero é nil.

  • Loop for no canal: O loop for pode percorrer os valores enviados no canal até que seja fechado.

    Sintaxe:

    for item := range Chnl { 
         // A expressão...
    }
    package main 
    import "fmt"
      
    func main() { 
      
        // Usar a função make() para criar um canal
        mychnl := make(chan string) 
      
        // Goroutine anônima 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "w3codebox
            close(mychnl) 
        } 
      
        //Usar loop for
        for res := range mychnl { 
            fmt.Println(res) 
        } 
    }

    Saída:

    GFG
    gfg
    Geeks
    w3codebox
  • Comprimento do canal:No canal, você pode usarFunção len()Encontrar o comprimento do canal. Aqui, o comprimento representa o número de valores enfileirados no buffer do canal.

    package main 
      
    import "fmt"
    func main() { 
      
        // Usar a função make() para criar um canal 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Usar a função len() para encontrar o comprimento do canal 
        fmt.Println("Comprimento do canal: ", len(mychnl)) 
    }

    Saída:

    Comprimento do canal:  4
  • Capacidade do canal:No canal, você pode usar a função cap() para encontrar a capacidade do canal. Aqui, a capacidade representa o tamanho do buffer.

    package main
    import "fmt"
    func main() {
        // Usar a função make() para criar um canal
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Usar a função cap() para encontrar a capacidade do canal
        fmt.Println("Capacidade do canal: ", cap(mychnl))
    }

    Saída:

    Capacidade do canal:  5
  • Select e instruções case em canais:No go语言中,a instrução select é semelhante a uma instrução switch sem parâmetros de entrada. No uso de canais, a instrução select executa uma única operação entre múltiplas operações fornecidas pelos blocos de caso.