Introdução ao Zig: Primeiros Passos com a Linguagem

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:

  1. const std = @import("std") — Importa a biblioteca padrão do Zig. O @import é um builtin que carrega módulos.

  2. 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 retornar void (nada) ou um erro. Isso faz parte do sistema de tratamento de erros do Zig.

  3. std.io.getStdOut().writer() — Obtém um writer para a saída padrão (stdout). O Zig usa interfaces genéricas para I/O.

  4. try stdout.print("Olá, mundo!\n", .{}) — O try propaga automaticamente qualquer erro que print possa 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:

  1. Strings e Arrays — Entenda slices, arrays e manipulação de strings
  2. Structs, Enums e Unions — Crie tipos de dados customizados
  3. Tratamento de Erros — Domine o sistema de erros do Zig
  4. Gerenciamento de Memória — Allocators e controle manual de memória
  5. 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!

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.