Intro Golang e comparação de desempenho de API com Node.js
A linguagem de programação Go ou Golang foi criada pela Google, nasceu em 2007. Uma das motivações para a criação da linguagem, foi que muitos de seus sistemas eram feitos em C e C++, e o processo de compilar esses programas, acabava se tornando complexo e demorado. Além das necessidades básicas de ter uma linguagem que proporcionava para seus sistemas um ótimo desempenho, escalabilidade e facilidade de manutenção.
Então, em 2009, ela foi oficialmente lançada, ficando em fase beta até 2011.
Convenções e diretrizes da linguagem
A Google, cansada de ter tais problemas, muitas vezes já conhecidos e mapeados, tomou uma decisão de impacto: Criar uma linguagem do zero, que facilitasse seus projetos e principalmente ajudasse em projetos complexos. Então, definiu diretrizes e convenções para essa nova linguagem:
- Programação concorrente nativa: Sem precisar utilizar bibliotecas externas para utilizar essa funcionalidade. Em Go existe o recurso de goroutines, que é uma thread leve de execução, então você pode executar um código paralelamente chamando a palavra
go
, conforme o exemplo abaixo, a funçãoprint
é executado pela main goroutine e também executado pela nova goroutine criada na linha 10.
- Modularização: Funcionalidades dividida em pacotes, e importadas conforme a necessidade.
- Compilada: Desempenho que apenas código compilado é capaz de fornecer.
- Simplista: Foco na velocidade, poucas palavras reservadas. Muitos recursos de linguagens de alto nível removidas, como Classes, Heranças, Try/Catch, Overloads de métodos…
- Sem ponto e vírgula, chaves depois da instrução do código e tab para indentação 😎: Menos preocupação de como organizar o código e mais produtividade para o desenvolvedor.
Variáveis
Go é uma linguagem com tipagem estática.
Go é uma tentativa de combinar a facilidade de programação de uma linguagem interpretada e dinamicamente tipificada com a eficiência e segurança de uma linguagem compilada estaticamente tipificada.
Declarações de variáveis:
As variáveis podem ser definidas dizendo seu tipo, conforme abaixo, name
do tipo string e age, size
do tipo int. E outro recurso muito bom do Go é inferência nas variáveis.
var name string = "Ronaldinho"
var age, size int = 38, 181
Inferência de variáveis: A declaração da variável (name) acima e abaixo vai resultar no mesmo resultado. Pois o Go tem essa inferência de tipo da variável, no exemplo string.
name := "Ronaldinho" // infere uma string a variável name
Assim como C e C++, entre outras, Golang suporta ponteiros. Um ponteiro é aponta para um endereço de memória, que no caso contém o valor de uma determinada variável.
Structs
Não existem classes e herança em Go, mas tem as Structs (estruturas definidas pelo desenvolvedor). Algo parecido com classes da orientação ao objeto. Exemplo abaixo, struct person, possuem as propriedade nome e idade e construindo a pessoa na linha 12:
Funções
Uma função é um grupo de instruções que juntas executam uma tarefa, que recebem ou não parâmetros e retornam ou não valores, igual em outras diversas linguagens.
Para definir Funções e types visíveis (publicas) fora do pacote, devem começar com letra maiúscula, caso minúscula só serão visíveis (privada) no mesmo pacote. Outro recurso muito legal do Go, que uma função pode ter múltiplos valores de retorno, então é possível uma função por exemplo retornar 2 valores (string, int).
Methods
Como em Go não existem classes, mas podemos definir structs e definir methods para estas estruturas. Um method é uma função que tem um receptor definido. Como exemplo abaixo, temos a receptor (struct) User e um method Greeting que recebe o (u User), que pode ser invocado pela struct User, conforme a linha 17.
API Golang
Então por que não utilizar Go, em APIs e microservices, sendo que é uma linguagem muito rápida, trabalha muito bem com concorrência e a comunidade cada vez maior e devs querendo aprender Go. Um detalhe que um HTTP Server em Go cria-se uma nova goroutine a cada nova requisição, tornando algo super escalável.
Sendo assim, um simples exemplo de API em Go para aplicar os conceitos sem e com goroutines. E depois poder fazer uma breve comparação dos resultados obtidos com a resolução do mesmo problema com o Node.js + Koa.
Ideia da API:
A ideia foi construir uma API simples e tenha apenas um endpoint (GET), e esse recurso retorne uma lista de animais com seu nome e o link de uma imagem random do animal. Olhando o repositório de APIs públicas, descobri 3 APIs de animais que retornam um link da imagem random do animal, Random Dog 🐶, Random Cat 😺 e Random Fox 🦊. Ficando o retorno assim (Nome do animal + link da imagem do animal):
[
{
"name": "Dog",
"img": "link"
},
{
"name": "Cat",
"img": "link"
},
{
"name": "Fox",
"img": "link"
}
]
Construindo a API em Go
Para a construção da API utilizei o Chi para Router e configurações do middleware, já para configuração o Viper.
Core da API
Primeiro a criação do arquivo main.go
, que é core do nosso programa. Criando o router, definindo as configurações de middleware e importando nossos pacotes.
Depois criando nosso pacote animals, que é onde está nossa lógica
A lógica que envolve animals, fica isolada no seu pacote. Primeiro as requisições para as APIs externas dos animais ficaram sem goroutines e channels, conforme a imagem, executando síncronas.
Depois, alterando a lógica das requisições para funcionarem paralelamente, com o recurso de goroutines e channels para troca de dados de cada goroutine, ficando assim:
Tendo esses 2 exemplos funcionando, podemos realizar os testes e verificar o desempenho. Para a comparação e análise, realizei a implementação do mesmo problema usando Node.js + Koa, primeiro deixando as chamadas síncronas e depois alterando para assíncronas também. Não entrarei adentro sobre o exemplo feito em Node.js agora, mas talvez em um próximo post.
O código fonte do exemplo em Go com Chi disponível em — https://github.com/richardbertozzo/first-api-go e código fonte do exemplo em Node.js + Koa disponível em — https://github.com/richardbertozzo/api-koa-example.
Testes de desempenho
Então realizei 10 requests para cada API separadamente, em cada uma das etapas. Primeiro na API de Go sem implementação de goroutines, que realizava essas 3 chamadas para as API externas dos animais síncronas e registrando a response time de cada uma dessas 10 requisições. Então, depois para a API em Go com goroutines e channels e também registrei os resultados. E realizando na API em Node + Koa, do mesmo modo guardado os response time das requisições.
Obs: Os testes foram realizados localmente e considerando o response time das APIs externas na média fossem iguais.
Resultados
Como podemos ver os resultados obtidos. As 2 que tiverem melhor resultado foram a Go c/ goroutines (média = 342,6 ms) e Node async (média = 802,1 ms). Vendo isso, que a diferença de response time entre a Go c/ goroutines para Node async é muito grande, o response time do API em Node demorou mais que dobro em milissegundos.
Desta maneira, o Golang é uma ótima opção para criarmos APIs e microservices. Muito rápida, escalável, modular, trabalhando muito bem com programação concorrente e facilitando muito para os desenvolvedores. Mesmo assim, é importante analisarmos e estudarmos qual a melhor linguagem ou ferramenta para resolver um problema ou contexto que temos, mas Go com certeza é uma das melhores opções para este contexto e entre outros em todo seu ecossistema.
Enfim, para mim é uma linguagem nova e vou continuar estudando e resolvendo coisas com o Go, e era uma linguagem que estava querendo muito aprender e com certeza me chamou muito atenção seus recursos e desempenho.
Algumas referências que utilizei e são muito boas e indico para compreender melhor a linguagem são The Little Go Book, Construindo Aplicações Web em Golang e para construir a base da API utilizei o artigo do Anthony Alaribe — How I structure production grade REST API’s in Golang. E este curso totalmente em português e grátis — https://greatercommons.com/learn/golang-ptbr. Além da documentação do Go.
That’s it. Um pouco sobre meu estudo da linguagem, uma linguagem que tem muitos recursos e formas de utilizar que com certeza não cabe num simples post, e que pretendemos criar algo com ela aqui na Delivery Much 😁. Fiquem avonts para críticas, dúvidas e elogios.