Como colocar rótulo em looping

Não sei vocês, mas a primeira vez que “ouvi” falar dessa feature foi há algumas semanas atrás. Mais uma vez, não foi em nenhum blog post ou vídeo do youtube que ví a utilização dessa feature, mas sim no código fonte da linguagem.

Com a minha experiência em outras linguagens, sempre que tinha que lidar com um looping dentro de outro, a maneira mais comum de fazer um “break” dos 2 loopings era com uma variável de controle.

Nessa estratégia, o looping interno altera essa variável e faz um break. Com seu valor alterado, o looping externo também faz um “break”.

Leia mais »

Implementando um worker pool

Agora que já falamos praticamente tudo que havia para ser falado sobre goroutines e channels, vamos utilizar esse conhecimento para implementar um worker pool.

Se você não conhece o termo, um worker pool é basicamente uma coleção de threads que ficam esperando tarefas serem atribuídas a elas. Quando a thread finaliza a tarefa que foi atribuída, se torna disponível novamente para execução de uma nova tarefa.

Antes de começar a meter a mão na massa, vou deixar aqui o link para os outros posts da série sobre goroutines e channels.

O worker pool que vamos implementar irá somar os dígitos passados e armazenar o resultado.

Leia mais »

Múltiplos channels e a cláusula select

Dando continuidade ao nosso estudo de goroutines e channels, nesse post vamos falar sobre uma cláusula pouco utilizada.

Antes de começar, vou deixar os links para os outros posts caso você tenha perdido algum da série.

A cláusula select é utilizada para que uma função consiga trabalhar com múltiplos channels. Ela bloqueia a execução da função até que um dos channels esteja pronto para ser executado. Caso mais de um channel esteja pronto para ser executado, ela selecionará de forma aleatória qual executar.

Para tentar ficar um pouco mais claro, vamos escrever um pequeno programa para ilustrar o comportamento.

Leia mais »

Trabalhando com generics

Se você está no mundo Go a algum tempo, com certeza já ouviu falar desse carinha ai. Para aqueles que estão chegando agora, generics é uma das features mais pedidas/aguardadas desde que a linguagem foi liberada para o mundo.

Como já falamos em outros posts, Go é uma linguagem de tipagem forte, ou seja, sempre precisamos declarar o tipo da variável, parâmetros de uma função e seus retornos. Isso acaba fazendo com que, em algumas ocasiões, seja necessário duplicar nosso código só para que ele atenda dois tipos diferentes de dados.

Um exemplo básico desse problema seria uma função que soma uma lista de valores, onde sem generics, caso fossemos somar int64 e float64, seria necessário criar duas funções basicamente iguais, só mudando o tipo de dado do parâmetro e do retorno.

Leia mais »

Aguardando execução de múltiplas goroutines

Pense em um cenário onde você abra centenas ou talvez milhares de goroutines, porém que essa quantidade não seja fixa.

Utilizar um channel para controlar a quantidade de goroutines que já finalizaram a execução pode ser muito trabalhoso e em alguns casos até impossível já que, para um channel simples, teriamos que esperar a execução de cada goroutine antes de iniciar a próxima.

Se resolvemos usar um channel com buffer, teremos que especificar sua capacidade durante sua criação, o que também pode nos levar a criar um buffer muito pequeno, onde não conseguimos iniciar todas as goroutines que queremos de uma só vez.

Se você quiser saber mais sobre goroutines e channels antes de continuar, vou deixar aqui a lista com os 3 últimos posts onde abordamos esses assuntos:

Bom, mas se gerir a execução das goroutines com channels pode ser trabalhoso ou em alguns casos até mesmo inviável, como podemos fazer?

Leia mais »

Buffer de mensagens em channels

Dando continuidade ao nosso estudo sobre channels, nesse post vamos falar sobre como fazer buffer de mensagens.

Até agora, todos os exemplos que vimos de channels no post “O que são e como utilizar channels” não fazem buffer das mensagens, ou seja, ao escrever uma mensagem no channel, a goroutine que escreveu fica aguardando até que outra goroutine faça a leitura daquela informação. Somente após a leitura é que a goroutine de escrita consegue voltar a escrever algo no channel.

Utilizar buffer de mensagens faz com que a goroutine de escrita seja bloqueado de escrever no channel somente quando o buffer estiver cheio. Já a de leitura só ficará bloqueada quando o buffer estiver vazio. Logo, utilizar um buffer de mensagens pode ajudar com que o trabalho das goroutines seja mais fluido.

Para criar um channel com buffer, tudo que precisamos fazer é passar um parâmetro adicional na sua criação para definir a capacidade máxima.

Leia mais »

O que são e como utilizar channels

Algumas semanas atrás fizemos um post falando sobre o que são e como funcionam as goroutines (link do post). Nesse post, mencionamos sobre os channels quando fizemos um “fix” para que o programa esperasse a execução da goroutine antes de terminar.

No post de hoje vamos aprofundar um pouco sobre o que são os channels e como podemos usá-los.

Podemos pensar em channels como sendo uma espécie de tunel de comunidação entre goroutines, onde uma goroutine consegue enviar informações para outra antes mesmo de terminar sua execução. Nesse mesmo cenário, a goroutine que recebe a informação, ficaria pausada até as informações chegarem.

Quando vamos declarar um channel ou inicializa-lo, precisamos associar um tipo de dado a ele. Esse tipo de dado é o tipo que ele estará apto à transportar entre goroutines.

Leia mais »

O que são e como funcionam as Goroutines

Na semana passada explicamos a diferença entre concorrência e paralelismo (link do post), o que serviu de base para o post de hoje, onde vamos explicar as famosas goroutines.

Goroutines são funções ou métodos executados em concorrência. Podemos pensar nelas como uma especie de lightweight thread que são gerenciadas pelo runtime do Go.

Chamamos de lightweight thread pois o custo para sua criação é muito menor quando comparada com um thread de verdade. Outro ponto positivo é que o runtime consegue aumentar ou diminuir a quantidade de goroutines de acordo com a necessidade da aplicação, enquanto o número de thread normalmente é fixo.

Leia mais »