Golang: Desmistificando 채널 - Range e close

우산도 범위 e 닫기



Se você tiver um canal, você pode receber mensagens usando um for range , parecido com percorrer um array ou slice.

Só que a diferença é que um for range em um canal vai ficar repetindo até o canal ser fechado. Se o canal nunca for fechado, isso vai fazer um loop infinito.

ch := make(chan struct{})

// loop infinito porque o channel nunca é fechado
for val := range ch {
}


Para fechar um canal é muito simples, porém deve ser feito com cuidado, porque se você fechar um canal e tentar enviar isso vai causar um panic .

Então tem duas regras básicas que você pode seguir para fechar um canal:
  • Você deve fechar na função que envia, porque so ela sabe quando pode fechar
  • Você deve garantir que está fechando depois de todas as goroutine terem terminado de enviar

  • Não tem problema tentar ler de um channel fechado em um range:

    ch := make(chan int)
    close(ch)
    
    for val := range ch {
        // não vai entrar aqui porque não tem nada para ser lido e não vai
        // repetir porque o channel está fechado
    }
    


    Você pode seguramente fechar um channel depois de ter enviado todos os valores:

    func process(values []int, results chan string) {
    
        // neste caso eu estou usando WaitGroup pra garantir que todas as
        // goroutines já escreveram no channel antes de poder fechá-lo
        wg := sync.WaitGroup{}
        wg.Add(len(values))
    
        // faço um processamento concorrente de values
        for _, val := range values {
            go func() {
                ...
            }()
        }
    
        // quando todas as goroutines terminarem, passa do Wait
        wg.Wait()
    
        // todas as goroutines já finalizaram, posso seguramente fechar o canal
        close(results)
    }
    

    좋은 웹페이지 즐겨찾기