Zig é uma linguagem de programação de sistemas moderna que oferece performance comparável a C, mas com muito mais segurança e ergonomia. Neste tutorial completo, vamos dar os primeiros passos com Zig: desde a instalação até a compreensão dos conceitos fundamentais que tornam essa linguagem especial.
Se você quer entender melhor o que é Zig e por que ela está ganhando popularidade, confira nosso artigo O que é Zig?.
Por que aprender Zig?
Antes de começar, vale entender o que torna Zig diferente de outras linguagens:
- Performance de C sem os problemas de C — mesmo poder, sem comportamento indefinido oculto
- Sem garbage collector — controle total de memória com allocators explícitos
- Cross-compilation nativa — compile para 30+ plataformas com um único comando
- Interoperabilidade com C — importe headers C diretamente sem wrappers
- Comptime — execute código em tempo de compilação para metaprogramação poderosa
Empresas como Uber, Cloudflare e o projeto Bun já usam Zig em produção. Para mais detalhes, veja por que aprender Zig.
Instalando o Zig
A instalação do Zig é simples em qualquer sistema operacional. Para um guia detalhado com todas as opções, confira nosso tutorial de instalação do Zig.
Linux e macOS
A forma mais rápida é baixar o binário pré-compilado do site oficial:
# Baixe a versão mais recente (substitua pela URL atualizada)
curl -LO https://ziglang.org/download/zig-linux-x86_64.tar.xz
# Extraia o arquivo
tar -xf zig-linux-x86_64.tar.xz
# Adicione ao PATH (adicione ao seu .bashrc ou .zshrc para ser permanente)
export PATH=$PATH:$PWD/zig-linux-x86_64
No macOS, você também pode usar o Homebrew:
brew install zig
Windows
No Windows, use o gerenciador de pacotes Scoop ou Chocolatey:
# Via Scoop
scoop install zig
# Via Chocolatey
choco install zig
Verificando a instalação
Após instalar, verifique se tudo está funcionando:
zig version
Você deve ver algo como 0.13.0 ou a versão mais recente. Se o comando não for encontrado, verifique se o diretório do Zig está no seu PATH.
Seu primeiro programa em Zig
Vamos criar o clássico “Olá, mundo!” em Zig. Crie um arquivo chamado hello.zig:
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Olá, mundo!\n", .{});
}
Compile e execute:
zig build-exe hello.zig
./hello
Você verá Olá, mundo! no terminal.
Entendendo cada linha
Vamos analisar o código em detalhe:
const std = @import("std")— Importa a biblioteca padrão do Zig. O@importé um builtin que carrega módulos.pub fn main() !void— Declara a função principal pública. O!voidé um tipo especial chamado error union: significa que a função pode retornarvoid(nada) ou um erro. Isso faz parte do sistema de tratamento de erros do Zig.std.io.getStdOut().writer()— Obtém um writer para a saída padrão (stdout). O Zig usa interfaces genéricas para I/O.try stdout.print("Olá, mundo!\n", .{})— Otrypropaga automaticamente qualquer erro queprintpossa retornar. O.{}é uma tupla vazia de argumentos.
Variáveis e constantes
No Zig, existem duas formas de declarar valores:
const — Valores imutáveis (preferido)
const x: i32 = 42; // tipo explícito
const nome = "Zig Brasil"; // tipo inferido ([]const u8)
const pi = 3.14159; // tipo inferido (comptime_float)
var — Valores mutáveis
var contador: u32 = 0;
contador += 1; // OK — variáveis podem ser modificadas
contador = 10; // OK
Dica importante: O Zig encoraja o uso de const sempre que possível. Se você declarar um var e nunca modificar o valor, o compilador vai emitir um aviso.
Tipos básicos
O Zig tem um sistema de tipos explícito e previsível:
// Inteiros com tamanho explícito
const a: i8 = -128; // inteiro com sinal, 8 bits
const b: u16 = 65535; // inteiro sem sinal, 16 bits
const c: i32 = 42; // inteiro com sinal, 32 bits
const d: u64 = 1000; // inteiro sem sinal, 64 bits
// Ponto flutuante
const e: f32 = 3.14; // 32 bits
const f: f64 = 2.718; // 64 bits (precisão dupla)
// Booleano
const ativo: bool = true;
// Tamanho de ponteiro (usize — depende da plataforma)
const tamanho: usize = 100;
Para aprender mais sobre os tipos de dados, incluindo arrays, slices e strings, confira nosso guia de Strings e Arrays em Zig.
Funções
Funções em Zig são declaradas com fn e têm tipos explícitos para parâmetros e retorno:
const std = @import("std");
fn somar(a: i32, b: i32) i32 {
return a + b;
}
fn dividir(a: f64, b: f64) !f64 {
if (b == 0) return error.DivisaoPorZero;
return a / b;
}
pub fn main() !void {
const resultado = somar(10, 20);
std.debug.print("Soma: {}\n", .{resultado});
const divisao = try dividir(10.0, 3.0);
std.debug.print("Divisão: {d:.2}\n", .{divisao});
}
Note como dividir retorna !f64 — um error union que pode ser um f64 ou um erro. Esse é o sistema de tratamento de erros do Zig em ação: explícito, sem exceções, sem surpresas.
Controle de fluxo
If/else
const idade: u8 = 25;
if (idade >= 18) {
std.debug.print("Maior de idade\n", .{});
} else {
std.debug.print("Menor de idade\n", .{});
}
if como expressão
Diferente de C, o if em Zig pode ser usado como expressão:
const status = if (idade >= 18) "adulto" else "menor";
While
var i: u32 = 0;
while (i < 10) : (i += 1) {
std.debug.print("{} ", .{i});
}
For (iteração sobre slices)
const nomes = [_][]const u8{ "Ana", "Bruno", "Carlos" };
for (nomes) |nome| {
std.debug.print("Olá, {s}!\n", .{nome});
}
Defer — limpeza garantida
Uma das funcionalidades mais poderosas do Zig é o defer, que garante que uma ação será executada quando sair do escopo atual:
const std = @import("std");
pub fn main() !void {
const allocator = std.heap.page_allocator;
const buffer = try allocator.alloc(u8, 1024);
defer allocator.free(buffer); // será executado ao sair da função
// Use o buffer com segurança...
// A memória será liberada automaticamente
}
Isso elimina a maioria dos memory leaks comuns em C. Para entender mais sobre como o Zig gerencia memória, veja nosso tutorial sobre gerenciamento de memória.
Compilando com zig build
Para projetos maiores, o Zig tem um sistema de build integrado que substitui ferramentas como Make, CMake ou Cargo:
# Inicializar um novo projeto
zig init
# Compilar o projeto
zig build
# Compilar e executar
zig build run
O arquivo build.zig define toda a configuração do projeto — dependências, targets, testes — tudo em Zig puro, sem linguagens de configuração separadas.
Próximos passos
Parabéns! Você já sabe o básico do Zig. Para continuar sua jornada, recomendamos:
- Strings e Arrays — Entenda slices, arrays e manipulação de strings
- Structs, Enums e Unions — Crie tipos de dados customizados
- Tratamento de Erros — Domine o sistema de erros do Zig
- Gerenciamento de Memória — Allocators e controle manual de memória
- Comptime — A funcionalidade mais poderosa do Zig
Ou se você vem de outra linguagem, temos guias especializados:
Explore todos os nossos tutoriais em português e junte-se à comunidade Zig Brasil!