Como executar testes rápidos em Go

Se você trabalha ou já trabalhou em um grande projeto com uma alta cobertura de testes, com certeza você já passou raiva na hora de executar os testes da aplicação localmente.

Isso por que, quanto maior o projeto e mais bem coberto por testes, maior o tempo para executar todas as validações.

Pois bem, hoje venho te mostrar duas formas de continuar com uma ótima cobertura de testes, porém economizar um bom tempo na hora de executá-los localmente ou na abertura de PRs.

Leia mais »

gonew: Como criar projetos a partir de templates

Ouvindo aos pedidos da comunidade, mesmo que não incorporado oficialmente ao CLI do Go ainda, o time de desenvolvimento da linguagem Go criou um novo programa capaz de ajudar a iniciar novos projetos. Seu nome, pelo menos por enquanto, gonew.

Como dito no parágrafo anterior, a finalidade desse novo programa é auxiliar na criação de novos projetos Go. Com ele, podemos utilizar um repositório template como base para novas aplicações.

Sem mais delongas, vamos meter a mão na massa, ou melhor, no teclado.

Instalação

Para conseguir utilizar esse novo programa, precisamos tê-lo instalado. A forma mais fácil, já que você muito provavelmente tem o Go instalado na sua máquina, é utilizar o comando go install.

go install golang.org/x/tools/cmd/gonew@latest
Leia mais »

Arquitetura hexagonal: Como implementar ports

Dando continuidade à série de posts sobre arquitetura hexagonal, nesse post implementaremos os ports do package category.

Se você está chegando agora ou se gostaria de relembrar, até o momento nós já:

Ports para atores Driven

Como é através de ports que o core da aplicação se comunicará com o mundo externo e, os atores do tipo driven são chamados a partir do core, a primeira coisa que vamos fazer é definir uma interface para esse tipo de ator.

type Repository interface {
	FindAll() ([]*Category, error)
	FindById(id string) (*Category, error)
	Save(category *Category) error
	Delete(id string) error
}
Leia mais »

Benchmark: ORM vs SQL puro

Finalmente tive tempo para sanar, com dados, uma das minhas e, imagino que de várias outras pessoas, maiores dúvidas quando se trata de Go e banco de dados. Qual a diferença, ao nível de consumo de recurso e performance, entre utilizar GORM vs escrever SQL na unha.

Para ficar mais fácil a leitura, separei o post em tópicos. Iniciarei explicando como fiz o setup, as funções comuns e realizei a execução dos benchmarks. Depois, separo o código do benchmark, assim como o resultado, em ações de CRUD.

Setup

Primeiramente, criei os packages entities, orm e std. Dentro do package entities, criei uma struct para ser utilizada em todos os benchmarks.

package entities

type Category struct {
    ID          int64  `gorm:"column:id;primaryKey"`
    Name        string `gorm:"column:name"`
    Description string `gorm:"column:description"`
}
Leia mais »

Benchmark: conexão sempre aberta vs uma conexão por chamada

Como eu nunca havia visto um benchmark para mostrar as diferenças entre, abrir uma conexão no início do programa e utilizá-la como dependência e, abrir uma nova conexão a cada chamada, resolvi fazê-la.

Embora a maioria das pessoas que converso saberem a resposta correta, não sei se, assim como eu, elas têm a ideia de quão grande é a diferença entre essas abordagens.

Mas antes de ver o resultado, mostrarei como construí o benchmark.

Conexão & Dados

Bem simples, para abrir a conexão sqlite3, criei uma função chamada Open.

package connections  

import (  
    "database/sql"  

    _ "github.com/mattn/go-sqlite3"  
)  

// Open a connection with a sqlite3 database
func Open() (*sql.DB, error) {  
    return sql.Open("sqlite3", "test.db")  
}
Leia mais »

Como organizar projetos em um mono-repo

No primeiro post sobre mono-repo, tentei trazer de forma menos técnica, quais os benefícios e vantagens, assim como qual o fator determinante para o sucesso desse tipo de abordagem.

Nesse post, vamos falar um pouco sobre a organização dos projetos e packages dentro de um mono-repo.

Workspace

Embora uma das principais vantagens de um mono-repo seja facilidade no compartilhamento de código, é preciso determinar os limites desse compartilhamento, ou seja, precisamos definir um espaço onde somente algumas pessoas tem “autorização” para realizar mudanças.

Esse espaço, também conhecido como workspace, é o primeiro nível de separação dentro de um mono-repo, ou seja, uma pasta criada na raiz do repositório.

Leia mais »

Por que minha empresa precisa de um mono-repo?

Há um bom tempo que se houve falar sobre mono-repositório ou, para os mais íntimos, mono-repo. Essa abordagem de armazenamento de código consiste em ter um único repositório para todas as aplicações.

Embora possa parecer assustador – imagine todos os times da área de engenharia da sua empresa trabalhando em um mesmo repositório -, existem grandes benefícios em se optar por essa abordagem.

Nesse primeiro post sobre o mono-repo, trago as respostas para alguns questionamentos que ouço com frequência.

Fique tranquilo, as respostas que vou listar aqui não são meramente imaginativas, mas sim com base na experiência que tenho tido auxiliando na construção de um mono-repo.

Benefícios

Pensar em 30, 70, 200 ou até mais pessoas trabalhando em um mesmo repositório pode parecer caótico. No entanto, desde que feita organizadamente, os benefícios são muito grandes.

Leia mais »

Como utilizar logs estruturados com log/slog

Lançado recentemente, o Go 1.21 trouxe um novo package padrão na linguagem, o log/slog. Embora Go tenha um package de logs desde seu lançamento, ao longo dos anos, ficou claro que as aplicações Go precisavam de logs estruturados.

Diferente do formato padrão em texto puro, logs estruturados utilizam o formato chave=valor, facilitando muito na hora de fazer parse, buscar e analisar os logs.

Embora existam vários packages open source que desempenham esse papel, sendo o logrus um dos mais famosos, todos os anos, a comunidade continuava pedindo ao time do Go que essa funcionalidade fosse adicionada ao package oficial da linguagem.

Nesse post, vou explorar um pouco desse package, mostrando as principais funções e formas de utilização.

Leia mais »

O que é e como configurar Taints e Toleration

No último post da série de Kubernetes, vimos como configurar NodeAffinity, PodAffinity e PodAntiAffinity. Nesse post, vamos ver como fazer o “NodeAntiAffinity”, ou seja, como configurar taint nos nodes e toleration nos pods.

Como você já deve ter percebido ao ler o post sobre Affinity e AntiAffinity, assim como o parágrafo anterior, não existe NodeAntiAffinity no Kubernetes. No entanto, caso um node precise ser configurado para repelir pods, o conceito de taint pode ser aplicado.

Embora possa parecer estranho ter um node dentro do cluster que repele pods, essa é uma prática comum ao configurar nodes com hardware específico, por exemplo que tenha GPU, assim como nodes dedicados a certas aplicações.

Taint

Como dito antes, ao contrário do affinity, cuja função é atrair os pods com determinadas labels, a função do taint é repelir pods com base em determinadas propriedades do node.

Leia mais »

Como implementar uma API com arquitetura hexagonal

Hoje iniciamos mais uma pequena série aqui no blog, onde vamos implementar uma pequena API utilizando arquitetura hexagonal. Essa série será dividida em pelo menos quatro posts, sendo esse primeiro a definição da estrutura de pastas.

Se você ainda não conhece muito bem essa arquitetura, convido você a ler o post onde explico a parte teórica da arquitetura hexagonal.

Agora que estamos todos no mesmo ponto, vamos começar a definir a estrutura de pastas desse pequeno projeto.

pkg

No root do projeto, como já é de costume, precisamos de uma pasta onde ficarão as implementações que podem ser compartilhadas com outros projetos, ou seja, implementações de packages que não tem nenhuma regra de negócio.

Leia mais »