Intro Golang e comparação de desempenho de API com Node.js

Richard Bertozzo
devmuch
Published in
7 min readJun 12, 2019
Golang mascote e seu novo logo.

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ção print é executado pela main goroutine e também executado pela nova goroutine criada na linha 10.
Exemplo de programação concorrente — goroutines.
  • 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.
Exemplo de if e declaração sem ponto e vírgula.

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:

Exemplo de struct.

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).

Exemplo de funções visíveis fora do pacote e retornando múltiplos valores.

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.

Exemplo de method com uma struct.

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.

Main.go com a criação da API com Chi.

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.

GET APIs externas sem goroutines.

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:

GET APIs externas com goroutines e channels.

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

Resultados em milissegundo (ms) das requisições para as APIs.

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 AlaribeHow 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.

--

--

Richard Bertozzo
devmuch
Writer for

Backend developer. Interested about microservices, Node.Js, Golang, Machine Learning.