Aula 33 – Tutorial Golang – Iteração sobre Valores Recebidos de um Canal

Aula 33 – Tutorial Golang – Iteração sobre Valores Recebidos de um Canal

Tutorial Golang

Tutorial Golang

Compartilho com vocês conteúdo de qualidade de forma gratuita como parte da missão do Código Fluente.

No entanto, também quero apresentar uma oportunidade imperdível de aprimorar suas habilidades em programação para alcançar um nível avançado.

Conheça agora mesmo o curso Master Full Stack clicando no link abaixo 👇 e confira!

Pacote Programador Fullstack

Pacote Programador Fullstack

Página principal do blog

Todas as aulas desse curso

Aula 32                        Aula 34

Redes Sociais:

facebook

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti

Lofi Music Zone Beats

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank

Aula 33 – Tutorial Golang – Iteração sobre Valores Recebidos de um Canal

Introdução:

Nesta aula, vamos explorar um conceito importante em programação concorrente em Go: a iteração sobre valores recebidos de um canal.

Veremos como a sintaxe do for e range pode ser utilizada para percorrer os valores recebidos de um canal e como o fechamento do canal afeta essa iteração.


package main

import "fmt"

func main() {
    // Criando um canal com capacidade para 2 valores
    // Iremos iterar sobre 2 valores no canal `queue`
    queue := make(chan string, 2)
    queue <- "one"
    queue <- "two"
    close(queue)

    // Iterando sobre os valores recebidos do canal usando `for` e `range`
    for elem := range queue {
        fmt.Println(elem)
    }
}

A função main é a entrada principal do programa

Nela criamos um canal chamado queue com capacidade para 2 valores usando make(chan string, 2).

Em seguida, enviamos dois valores para o canal queue usando o operador <-.

Fechamos o canal queue usando a função close(queue).

Isso indica que nenhum valor adicional será enviado para o canal.

Usamos um loop for e range para iterar sobre os valores recebidos do canal queue.

O loop continua até que o canal seja fechado e todos os valores sejam recebidos.

Em cada iteração, o valor recebido é armazenado na variável elem, e então o valor é impresso no console usando fmt.Println(elem).

O resultado será a impressão dos valores “one” e “two” que foram enviados e recebidos do canal queue.

Esse exemplo ilustra como utilizar o for e range para iterar sobre os valores recebidos de um canal em Go.

É uma forma eficiente de processar os valores recebidos do canal de forma sequencial.

Processamento Paralelo

Caso de uso

Ao usar goroutines para processamento paralelo, é comum utilizar canais para enviar e receber dados entre as goroutines.

A iteração sobre os valores recebidos de um canal permite processar os resultados simultaneamente.

Import do sync 

Por causa do import do sync, antes de rodar o código precisamos executar: go mod init <modulename>, para limpar e atualizar o arquivo go.mod e o arquivo go.sum.

Ele remove as dependências que não estão mais sendo utilizadas no projeto e adiciona as dependências necessárias com as versões corretas.

É útil para garantir que as dependências do projeto estejam atualizadas e corretas.

No meu caso, vou chamar o módulo de fluentcode.com.

go mod init fluentcode.com

Rode também o: go mod tidy para inicializar um módulo e gerenciar as dependências do projeto.

go mod tidy

Exemplo de código:


package main

import (
    "fmt"
    "sync"
)

func processWorker(id int, jobs <-chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        fmt.Printf("Worker %d processing job %d\n", id, job)
        // Realize o processamento do trabalho aqui
    }
}

func main() {
    jobs := make(chan int, 5)
    var wg sync.WaitGroup

    numWorkers := 3
    for i := 1; i <= numWorkers; i++ {
        wg.Add(1)
        go processWorker(i, jobs, &wg)
    }

    // Enviar trabalhos para os workers
    for i := 1; i <= 10; i++ {
        jobs <- i
    }
    close(jobs)

    // Aguardar a conclusão de todos os workers
    wg.Wait()
}

Neste exemplo, criamos goroutines (workers) que processam trabalhos em paralelo.

Os trabalhos são enviados para o canal jobs e cada worker itera sobre os valores recebidos desse canal usando o for e range.

A saída do código será algo semelhante a:

Worker 1 processing job 1
Worker 2 processing job 2
Worker 3 processing job 3
Worker 1 processing job 4
Worker 2 processing job 5
Worker 3 processing job 6
Worker 1 processing job 7
Worker 2 processing job 8
Worker 3 processing job 9
Worker 1 processing job 10

No entanto, é importante ressaltar que a ordem exata pode variar a cada execução do programa devido à concorrência dos workers.

Portanto, embora o primeiro worker comece a processar o job 1, não é garantido que ele terminará de processá-lo antes que outros workers iniciem seus próprios jobs.

Além disso, como o canal jobs tem uma capacidade de 5, o envio de jobs além desse limite ficará em espera até que os workers processem alguns jobs existentes e liberem espaço no canal.

Portanto, a ordem precisa de processamento e a distribuição exata dos jobs entre os workers podem variar a cada execução.

Função processWorker() do código acima

A função processWorker() representa a rotina de trabalho de cada worker.

Recebe o ID do worker, um canal jobs de onde ele recebe os trabalhos a serem processados e um ponteiro para um objeto sync.WaitGroup para indicar que o worker concluiu seu trabalho.

O loop: for job := range jobs, percorre o canal jobs e recebe os trabalhos à medida que são enviados.

Em seguida, o worker processa o trabalho, que é simulado com a impressão de uma mensagem.

O defer wg.Done() é usado para indicar que o worker terminou seu trabalho, decrementando o contador do sync.WaitGroup quando a função processWorker retorna.

Função main() do código acima

A função main() é responsável por configurar e coordenar os workers.

Criamos um canal jobs com uma capacidade de 5 para armazenar os trabalhos a serem processados.

Inicializamos uma variável wg do tipo sync.WaitGroup para sincronizar a finalização de todos os workers.

Definimos o número de workers desejado (numWorkers = 3) e, em seguida, iniciamos goroutines chamando a função processWorker() para cada worker.

Em seguida, enviamos 10 trabalhos para o canal jobs utilizando um loop for.

Fechamos o canal jobs para indicar que nenhum trabalho adicional será enviado.

Por fim, chamamos wg.Wait() para aguardar a conclusão de todos os workers, o que é indicado pelo wg.Done() em cada worker.

Consumo de Streams de Dados

Caso de uso

Em situações em que os dados estão sendo transmitidos continuamente em um canal, a iteração sobre os valores recebidos permite consumir esses dados conforme eles estão disponíveis, em tempo real.

Exemplo de código:


package main

import (
    "fmt"
    "time"
)

func dataProducer(data chan<- int) {
    for i := 1; i <= 5; i++ {
        data <- i
        time.Sleep(time.Second)
    }
    close(data)
}

func main() {
    data := make(chan int)

    go dataProducer(data)

    for value := range data {
        fmt.Println("Received:", value)
    }
}

Neste exemplo, temos uma goroutine dataProducer que envia valores para o canal data em intervalos de 1 segundo.

A função main() itera sobre os valores recebidos desse canal usando o for e range, imprimindo os valores à medida que são recebidos.

Esses são apenas dois casos de uso comuns em que a iteração sobre valores recebidos de um canal é aplicável.

A versatilidade dessa abordagem permite seu uso em uma ampla gama de cenários de programação concorrente.

Conclusão

Dominar a iteração sobre valores recebidos de um canal é essencial para o desenvolvimento de programas concorrentes eficientes em Go.

Ao compreender os conceitos abordados nesta aula, você estará um passo mais próximo de aproveitar todos os benefícios da programação concorrente em Go.

Continue praticando e explorando os recursos dessa poderosa linguagem!

#Golang #ProgramacaoConcorrente #IteracaoCanal #ForRange

Eu fico por aqui e agradeço a você pela audiência.

Até mais. 🙂

Página principal do blog

Todas as aulas desse curso

Aula 32                        Aula 34

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>