Como Zig pensa
Se você já programa, aprender Zig não é aprender if, for e struct de novo. Esses você traz de casa. O que Zig cobra, e o que faz o resto da linguagem se organizar quando você entende, é uma postura sobre o que um programa tem o direito de esconder de quem o lê. A maioria das linguagens modernas trabalha para poupar você dos detalhes: aloca memória por baixo dos panos, dispara um destrutor que você não escreveu, chama um operador sobrecarregado que parece uma soma mas faz uma requisição de rede. Zig faz a aposta oposta, e é essa aposta, não a sintaxe, que vale estudar primeiro.
As três ausências
Section titled “As três ausências”O lema que mais se repete sobre Zig é uma lista de coisas que a linguagem se recusa a ter, e vale levá-lo a sério porque quase toda decisão de design decorre dele.
Sem fluxo de controle escondido. Não há exceções que sobem a pilha por um caminho invisível, não há sobrecarga de operadores, não há goto disfarçado. Se o controle sai de uma função, foi porque você escreveu return, try, ou uma chamada explícita. Ler uma linha de Zig e saber o que ela pode ou não fazer é uma propriedade de projeto, não um acaso. A consequência prática é direta: a + b é sempre uma soma, e foo() é sempre uma chamada de função comum, nunca um efeito colateral disfarçado.
Sem alocação escondida. Nenhuma função da biblioteca padrão aloca memória sem receber um allocator como argumento. Isso soa burocrático até você perceber o que compra: a política de memória deixa de ser uma decisão da linguagem e passa a ser um parâmetro do seu código. A mesma estrutura de dados roda numa arena que é descartada de uma vez, num buffer fixo sem nenhuma syscall, ou num allocator que detecta vazamentos, e quem escolhe é quem chama, linha a linha. É o conceito que separa Zig de quase tudo, e o documento sobre allocators é o documento central da trilha por isso.
Sem memória escondida. Não há coletor de lixo rodando numa thread que você não vê, e não há destrutor implícito disparado na saída do escopo. A liberação de recursos é explícita, marcada com defer e errdefer, e fica visível no ponto onde acontece. Você paga o preço de nunca esquecer um free, e recebe em troca a ausência de pausas de GC e a certeza de saber, olhando o código, quando cada byte é alocado e liberado.
Erros são valores, não eventos
Section titled “Erros são valores, não eventos”Zig não tem exceções. Uma função que pode falhar declara isso no tipo de retorno, com um ! na frente: !u32 é “um u32 ou um erro”. O erro não interrompe o programa por um canal lateral; ele é um valor devolvido, que você é obrigado a tratar antes de usar o resultado. O try propaga o erro para cima, o catch o intercepta ali mesmo, e o errdefer desfaz o trabalho parcial quando a saída é por erro. Quem vem de Rust reconhece o Result, quem vem de Go reconhece o if err != nil, e quem viu Effect reconhece a ideia de promover a falha a cidadã de primeira classe do tipo. O tratamento de erro é onde essa família de ideias vira idioma.
Comptime no lugar de macros e genéricos
Section titled “Comptime no lugar de macros e genéricos”O recurso que mais distingue Zig de tudo que veio antes é o comptime: a capacidade de executar código Zig comum durante a compilação, com tipos sendo valores de primeira classe. Não há uma segunda linguagem de macros, não há um sistema de templates separado com suas próprias regras. Um genérico é uma função que recebe um type e devolve um type, escrita na mesma sintaxe do resto. Reflexão, geração de código e especialização são todos o mesmo mecanismo, e é ele que sustenta a biblioteca padrão inteira. É a parte da linguagem que mais recompensa o estudo, e o documento sobre comptime mostra por quê.
Custo zero, mas honesto
Section titled “Custo zero, mas honesto”Zig promete abstrações de custo zero (zero-cost abstractions), no mesmo sentido que C e Rust prometem: o que você não usa, não paga, e o que você usa não teria como ser escrito à mão de forma mais enxuta. A diferença de temperamento é que Zig prefere ser honesto a ser conveniente. Ele não esconde o custo atrás de açúcar sintático; quando algo é caro, o código deixa isso à mostra. Essa honestidade tem um preço em ergonomia que a própria comunidade admite, e é justo dizer que a linguagem ainda é pré-1.0, com a biblioteca padrão e o sistema de build mudando entre versões. Esta trilha escreve para o Zig de 2026 (a linha 0.15/0.16) e avisa onde a API é movediça.
O mapa da trilha
Section titled “O mapa da trilha”A ordem vai do concreto ao abstrato, porque cada camada só faz sentido sobre a anterior.
Modelo de memória é a base: stack e heap, ponteiros, slices, arrays, alinhamento. Sem entender onde os dados vivem e por quanto tempo, o resto não se sustenta.
Allocators é o documento central: como “sem alocação escondida” vira um padrão de projeto onde tudo recebe um allocator, e o catálogo de allocators que a std oferece.
Erros como valores formaliza o tratamento de falha: !T, try, catch, errdefer, o optional ?T como gêmeo para a ausência, e o contraste com Rust, Go e Effect.
Structs e composição mostra como Zig monta abstrações sem herança: métodos, namespaces, enums e as tagged unions que substituem o polimorfismo de subtipo.
Comptime é a virada: código em tempo de compilação, tipos como valores, reflexão e a maquinaria dos genéricos.
Build e interop com C cobre o build.zig, a compilação cruzada trivial e o @cImport, que faz de Zig um dos melhores cidadãos do ecossistema C.
SIMD e desempenho desce ao @Vector, ao alinhamento e à relação com cache e previsão de desvio, e fecha com uma nota sobre concorrência e o estado atual do modelo de I/O.
Praticar fecha com o que de fato ensina: ler código real e uma escada de projetos que termina num mini banco colunar.
Palavras-chave
Section titled “Palavras-chave”Conceitos: no hidden control flow, no hidden allocations, no hidden memory, erros como valores, optional, captura de payload, comptime, zero-cost abstractions, alocação explícita
Linguagem: Zig, !T, ?T, try, catch, orelse, errdefer, defer, comptime, @Vector, allocator
Contraste: C, Rust, Go, coletor de lixo, exceções, macros
Ecossistema: pré-1.0, Zig 0.15/0.16, biblioteca padrão, build.zig