Pular para o conteúdo principal

victorstein.dev

100/100 Dias de Golang - Fim!

# 100/100

Chegamos! Esse é o post 101, porque, como eu disse no dia 50, um blog de programação tinha que começar no índice 0.

No dia 0 a ideia era simples: “fazer um post todo dia e me forçar a estudar, nem que seja um pouco, de Golang todo dia”. E no dia 50 eu prometi que, no dia 100, faria de novo o índice de todos os posts agrupados por assunto. Promessa é dívida, então este post tem três partes: como foi a jornada, os números da série (calculados, claro, com um programa em Go) e o índice completo.

99/100 Dias de Golang - Iterators e embed

# Iterators e embed

No penúltimo post da série, dois recursos da linguagem que não têm muito a ver um com o outro, mas que aparecem cada vez mais em código Go moderno: os iterators, que chegaram no Go 1.23, e o embed, que permite colocar arquivos dentro do binário.

# Iterators

## O problema

O for range sempre funcionou com os tipos da linguagem: slices, arrays, maps, strings e channels. Desde o Go 1.22, funciona até com inteiros (for i := range 10). Mas e se criarmos a nossa própria coleção, como uma lista encadeada ou uma árvore? Até pouco tempo, as opções eram:

98/100 Dias de Golang - gRPC e Protocol Buffers

# gRPC e Protocol Buffers

Nesta série já fizemos aplicações se comunicarem de várias formas: TCP puro (dia 51), UDP (dia 54), WebSockets (dia 53) e, claro, APIs REST com JSON. Hoje vamos ver a forma mais comum de serviços conversarem entre si em arquiteturas de microsserviços: o gRPC.

O gRPC é um framework de RPC (Remote Procedure Call) criado pelo Google. A ideia do RPC é que chamar uma função em outro servidor pareça chamar uma função local:

97/100 Dias de Golang - Autenticação com JWT e Middlewares no Gin

# Autenticação com JWT e Middlewares no Gin

Em vários posts criamos APIs com o Gin (dia 43, a previsão do tempo, o Mini CI/CD…), mas todas tinham o mesmo problema: qualquer pessoa podia chamar qualquer endpoint. Hoje vamos resolver isso com uma API que tem cadastro, login e rotas protegidas, usando JWT para autenticação e middlewares do Gin para controlar o acesso.

Antes, dois conceitos que costumam ser confundidos:

96/100 Dias de Golang - SQL sem ORM com database/sql e sqlc

# SQL sem ORM com database/sql e sqlc

Até agora, sempre que precisamos de banco de dados usamos o GORM (dia 31 e no Mini CI/CD do dia 78). O GORM é prático: definimos structs, chamamos db.Create, db.Find e ele escreve o SQL por nós. Mas isso tem um preço: o SQL fica escondido, queries mais complexas viram uma sequência de métodos encadeados difícil de ler, e às vezes o ORM gera algo bem diferente do que imaginávamos.

95/100 Dias de Golang - Métricas com Prometheus e Tracing com OpenTelemetry

# Métricas com Prometheus e Tracing com OpenTelemetry

No post anterior vimos logging estruturado. Logs são ótimos para entender o que aconteceu em um evento específico, mas não respondem bem a algumas perguntas:

  • Quantas requisições por segundo a API está recebendo agora? Quantas estão dando erro?
  • O tempo de resposta piorou depois do último deploy?
  • Essa requisição demorou 2 segundos. Onde foi gasto esse tempo: no banco, numa API externa, no nosso código?

Para isso existem os outros dois “pilares” da observabilidade:

94/100 Dias de Golang - Logging estruturado com log/slog

# Logging estruturado com log/slog

No dia 38 usamos o pacote log e no dia 39 o Zap. O log é simples, mas só imprime texto. O Zap faz logging estruturado e é muito rápido, mas é uma dependência externa. Desde o Go 1.21, a biblioteca padrão tem uma terceira opção que fica no meio do caminho: o pacote log/slog (o “s” é de structured).

# Por que logging estruturado?

Compare esses dois logs:

93/100 Dias de Golang - Stack, Heap, Escape Analysis e Garbage Collector

# Stack, Heap, Escape Analysis e Garbage Collector

No post anterior o profiler mostrou que quase um terço do tempo do programa ia para o garbage collector, e que a versão otimizada fazia 21 alocações em vez de 320 mil. Mas o que exatamente é uma “alocação”? Por que algumas variáveis custam mais que outras? E o que o GC faz com elas? Hoje vamos olhar por baixo dos panos.

92/100 Dias de Golang - Profiling com pprof

# Profiling com pprof

No dia 27 vimos testes de benchmark, que respondem à pergunta “quão rápido é esse código?”. Mas quando o benchmark mostra que algo está lento, a próxima pergunta é: “lento onde?”. Dá para tentar adivinhar, sair colocando time.Now() pelo código… ou usar um profiler.

Um profiler observa o programa enquanto ele roda e mostra onde o tempo e a memória estão sendo gastos. O Go já vem com um, o pprof, sem precisar instalar nada.

91/100 Dias de Golang - Padrões de Concorrência - Worker Pool, Fan-out/Fan-in e errgroup

# Padrões de Concorrência

Lá nos dias 17 a 20 vimos as peças básicas de concorrência em Go: goroutines, WaitGroup, Mutex e channels. Com essas peças conseguimos fazer praticamente qualquer coisa, mas alguns problemas aparecem com tanta frequência que já existem “receitas” conhecidas para resolvê-los. Hoje vamos ver três delas: worker pool, fan-out/fan-in e o errgroup.

# Worker Pool

Imagine que temos 10.000 imagens para redimensionar. Criar uma goroutine para cada imagem é fácil, goroutines são baratas, mas cada uma vai abrir um arquivo, alocar memória, usar CPU… Com 10.000 rodando ao mesmo tempo podemos acabar com a memória da máquina, estourar o limite de arquivos abertos ou derrubar uma API externa com requisições demais.