Microservices com Go: Guia Completo
Go é a linguagem perfeita para microservices: rápida, compila para binário único, e tem excelente suporte a concorrência.
Por que Go para Microservices?
- Binários standalone — Sem dependências externas, deploy simples
- Baixo consumo de memória — Containers leves
- Startup instantâneo — Ideal para escalar
- Concorrência nativa — Goroutines são perfeitas para I/O
- Biblioteca padrão robusta — HTTP, JSON, gRPC incluídos
Arquitetura Básica
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Gateway │────▶│ Service A │────▶│ Database │
│ (API) │ │ (Users) │ │ (Postgres) │
└─────────────┘ └─────────────┘ └─────────────┘
│
│ ┌─────────────┐ ┌─────────────┐
└───────────▶│ Service B │────▶│ Redis │
│ (Orders) │ │ (Cache) │
└─────────────┘ └─────────────┘
Estrutura de um Microservice
user-service/
├── cmd/
│ └── main.go # Entrypoint
├── internal/
│ ├── handler/ # HTTP handlers
│ ├── service/ # Business logic
│ └── repository/ # Data access
├── pkg/
│ └── models/ # Shared models
├── Dockerfile
├── go.mod
└── go.sum
Service Básico
// cmd/main.go
package main
import (
"log"
"net/http"
"os"
"user-service/internal/handler"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
mux := http.NewServeMux()
// Health check - essencial para Kubernetes
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
// Rotas do serviço
mux.HandleFunc("/users", handler.ListUsers)
mux.HandleFunc("/users/", handler.GetUser)
log.Printf("Server starting on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}
Comunicação entre Services
HTTP/REST
// Chamando outro service
func GetUserFromService(userID string) (*User, error) {
resp, err := http.Get("http://user-service:8080/users/" + userID)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var user User
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return nil, err
}
return &user, nil
}
gRPC (Mais Performático)
// user.proto
syntax = "proto3";
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
}
message User {
string id = 1;
string name = 2;
string email = 3;
}
// Cliente gRPC
conn, err := grpc.Dial("user-service:50051", grpc.WithInsecure())
client := pb.NewUserServiceClient(conn)
user, err := client.GetUser(ctx, &pb.GetUserRequest{Id: "123"})
Docker
# Build stage
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /service ./cmd/main.go
# Runtime stage
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /service .
EXPOSE 8080
CMD ["./service"]
# Build e run
docker build -t user-service .
docker run -p 8080:8080 user-service
Docker Compose (Desenvolvimento)
version: '3.8'
services:
user-service:
build: ./user-service
ports:
- "8081:8080"
environment:
- DATABASE_URL=postgres://postgres:pass@db:5432/users
depends_on:
- db
order-service:
build: ./order-service
ports:
- "8082:8080"
environment:
- USER_SERVICE_URL=http://user-service:8080
- REDIS_URL=redis://redis:6379
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=pass
redis:
image: redis:7
Kubernetes
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
memory: "128Mi"
cpu: "100m"
Service
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
Padrões Essenciais
1. Circuit Breaker
import "github.com/sony/gobreaker"
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "user-service",
MaxRequests: 5,
Interval: 10 * time.Second,
Timeout: 30 * time.Second,
})
result, err := cb.Execute(func() (interface{}, error) {
return http.Get("http://user-service/users")
})
2. Retry com Backoff
func fetchWithRetry(url string, maxRetries int) (*http.Response, error) {
var resp *http.Response
var err error
for i := 0; i < maxRetries; i++ {
resp, err = http.Get(url)
if err == nil && resp.StatusCode == 200 {
return resp, nil
}
backoff := time.Duration(math.Pow(2, float64(i))) * time.Second
time.Sleep(backoff)
}
return nil, fmt.Errorf("max retries reached: %w", err)
}
3. Distributed Tracing
import "go.opentelemetry.io/otel"
tracer := otel.Tracer("user-service")
ctx, span := tracer.Start(ctx, "GetUser")
defer span.End()
Monitoramento
Métricas com Prometheus
import "github.com/prometheus/client_golang/prometheus"
var httpRequestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total HTTP requests",
},
[]string{"method", "endpoint", "status"},
)
func init() {
prometheus.MustRegister(httpRequestsTotal)
}
Logs Estruturados
import "go.uber.org/zap"
logger, _ := zap.NewProduction()
logger.Info("user created",
zap.String("user_id", user.ID),
zap.String("email", user.Email),
)
Checklist de Produção
- Health checks (/health, /ready)
- Graceful shutdown
- Configuração via environment variables
- Logs estruturados (JSON)
- Métricas Prometheus
- Tracing distribuído
- Circuit breakers
- Rate limiting
- Autenticação (JWT)
- Testes de integração
Veja Também
- API REST com Go — CRUD completo passo a passo
- Go com Docker — Multi-stage builds e imagens mínimas
- Concorrência em Go — Goroutines e Channels
- Testes em Go — Unit tests, benchmarks, mocks
- Empresas que Usam Go no Brasil — 948+ empresas contratando
- Vagas Go — Oportunidades para devs Go
- Salários Go — Quanto ganha um dev Go
Última atualização: Fevereiro 2026