Middle
Quais as consequências de ler de um canal fechado em Go?
sobes.tech IA
Resposta da IA
A leitura de um canal fechado devolve imediatamente o valor nulo do tipo de elementos do canal sem bloqueio. Se estiver presente um segundo parâmetro booleano devolvido, este será false.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1) // Canal com buffer
ch <- 1
close(ch)
val, ok := <-ch // Leitura de um canal fechado
fmt.Printf("Valor: %d, Aberto: %t\n", val, ok) // Será exibido "Valor: 1, Aberto: true"
val, ok = <-ch // Leitura repetida do mesmo canal fechado
fmt.Printf("Valor: %d, Aberto: %t\n", val, ok) // Será exibido "Valor: 0, Aberto: false"
// Leituras adicionais do canal fechado
val, ok = <-ch
fmt.Printf("Valor: %d, Aberto: %t\n", val, ok) // Será exibido "Valor: 0, Aberto: false"
}
Consequências principais:
- Obtenção de valor nulo: O programa não irá falhar, mas obterá o valor nulo padrão para o tipo de dados do canal.
- Indicador de encerramento: O segundo parâmetro booleano, se utilizado, torna-se
false, sinalizando que o canal está fechado e o valor obtido é nulo. - Leitura não bloqueante: A operação de leitura não bloqueará a goroutine.
- Sem pânico: Ao contrário de escrever em um canal fechado, ler de um canal fechado não provoca pânico.
Comparação da leitura de canais abertos e fechados:
| Estado do canal | Operação | Comportamento | Valor retornado (se houver o segundo parâmetro) |
|---|---|---|---|
| Aberto | <-ch |
Bloqueio até receber valor ou fechar | Valor, true |
| Aberto | val, ok := <-ch |
Bloqueio até receber valor ou fechar | Valor, true |
| Fechado | <-ch |
Obtenção imediata | Valor nulo |
| Fechado | val, ok := <-ch |
Obtenção imediata | Valor nulo, false |
O uso do segundo parâmetro booleano é a forma recomendada de determinar se um elemento real foi recebido do canal ou se o canal está fechado.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1)
ch <- 1
close(ch)
for {
val, ok := <-ch
if !ok {
fmt.Println("Canal fechado, saindo do ciclo.")
break
}
fmt.Printf("Valor recebido: %d\n", val)
}
}
Este comportamento permite encerrar elegantemente as goroutines que leem do canal após seu fechamento.