Introdução aos microsserviços em Go
A arquitetura de microsserviços tornou-se o padrão para construir aplicações escaláveis e tolerantes a falhas. A linguagem Go (Golang) é ideal para o desenvolvimento de microsserviços devido ao seu desempenho, suporte embutido para concorrência e simplicidade de implantação. Neste artigo, exploraremos os princípios básicos da construção de microsserviços em Go, criaremos um serviço simples com REST API, conectaremos um banco de dados e mostraremos como conteinerizar a aplicação com Docker.
Fundamentos da arquitetura de microsserviços
Microsserviços são uma abordagem onde a aplicação é dividida em serviços pequenos e implantados independentemente. Cada serviço é responsável por sua própria lógica de negócio e se comunica com outros através de protocolos leves (geralmente HTTP/REST ou gRPC).
Vantagens dos microsserviços em Go
- Desempenho: Go é compilado para código de máquina, proporcionando alta velocidade de execução.
- Concorrência: goroutines e channels permitem processar milhares de requisições eficientemente.
- Simplicidade de implantação: o arquivo binário não requer dependências externas.
- Biblioteca padrão embutida: pacotes como
net/http,encoding/jsone outros cobrem a maioria das tarefas.
Princípios-chave de design
- Responsabilidade única: cada serviço resolve uma única tarefa.
- Independência: os serviços podem ser desenvolvidos, testados e implantados separadamente.
- Baixo acoplamento: mudanças em um serviço não devem quebrar outros.
- Resiliência a falhas: a falha de um serviço não deve derrubar todo o sistema.
Prática: criando um microsserviço em Go
Vamos criar um microsserviço simples para gerenciamento de usuários. Ele fornecerá uma REST API para criar, ler, atualizar e deletar usuários (CRUD).
Passo 1: Inicialização do projeto
Crie um diretório para o projeto e inicialize o módulo Go:
mkdir user-servicecd user-servicego mod init github.com/yourusername/user-servicePasso 2: Estrutura do projeto
Organize o código em pacotes:
user-service/├── cmd/│ └── main.go├── internal/│ ├── handler/│ │ └── user.go│ ├── model/│ │ └── user.go│ └── repository/│ └── user.go├── go.mod└── go.sumPasso 3: Definindo o modelo de dados
Crie a estrutura do usuário no arquivo internal/model/user.go:
package model
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"`}Passo 4: Implementando o repositório
Para simplificar, usaremos um armazenamento in-memory. Crie internal/repository/user.go:
package repository
import ( "sync" "user-service/internal/model")
type UserRepository struct { mu sync.RWMutex users map[int]model.User nextID int}
func NewUserRepository() *UserRepository { return &UserRepository{ users: make(map[int]model.User), nextID: 1, }}
func (r *UserRepository) Create(user model.User) model.User { r.mu.Lock() defer r.mu.Unlock() user.ID = r.nextID r.nextID++ r.users[user.ID] = user return user}
func (r *UserRepository) GetByID(id int) (model.User, bool) { r.mu.RLock() defer r.mu.RUnlock() user, ok := r.users[id] return user, ok}
func (r *UserRepository) GetAll() []model.User { r.mu.RLock() defer r.mu.RUnlock() result := make([]model.User, 0, len(r.users)) for _, user := range r.users { result = append(result, user) } return result}
func (r *UserRepository) Update(id int, user model.Us