FAQ para Iniciantes em Zig — Primeiros Passos

FAQ para Iniciantes em Zig — Primeiros Passos

Se você está começando a aprender Zig, estas são as perguntas mais comuns que todo iniciante faz. Respostas claras e diretas para seus primeiros passos na linguagem.

1. Como instalo o Zig?

A maneira mais simples é baixar o binário pré-compilado do site oficial:

# Linux (extrair e adicionar ao PATH)
wget https://ziglang.org/download/zig-linux-x86_64.tar.xz
tar xf zig-linux-x86_64.tar.xz
export PATH=$PATH:$PWD/zig-linux-x86_64

# macOS via Homebrew
brew install zig

# Windows via scoop
scoop install zig

Para instruções detalhadas, consulte nosso guia de instalação.

2. Qual é o “Hello World” em Zig?

const std = @import("std");

pub fn main() void {
    std.debug.print("Olá, mundo!\n", .{});
}

Salve como hello.zig e execute com:

zig run hello.zig

3. Preciso saber C para aprender Zig?

Não, mas ajuda. Zig compartilha conceitos com C como ponteiros, memória manual e tipos de baixo nível. Se você nunca programou com essas ideias, precisará dedicar um tempo extra para entendê-las. Desenvolvedores vindos de Python, JavaScript ou Java conseguem aprender Zig, mas a curva é um pouco mais íngreme.

4. O que é const vs var?

  • const declara uma constante que não pode ser alterada depois de definida
  • var declara uma variável que pode ser reatribuída
const x: i32 = 42;    // imutável
var y: i32 = 10;      // mutável
y = 20;               // OK
// x = 99;            // ERRO: não pode alterar const

Zig incentiva usar const sempre que possível. O compilador dará erro se você usar var quando const bastaria.

5. O que são esses .{} que aparecem em todo lugar?

É a sintaxe de struct literal anônima, muito usada para passar argumentos. Em std.debug.print, o segundo argumento é uma tupla com os valores a formatar:

const nome = "Maria";
const idade: u32 = 25;
std.debug.print("Nome: {s}, Idade: {d}\n", .{ nome, idade });

O .{} vazio significa “sem argumentos para formatar”.

6. Por que preciso de try em tantos lugares?

Zig obriga o tratamento de erros. Quando uma função pode falhar, ela retorna um error union (!T). Você precisa lidar com o possível erro usando:

  • try — Propaga o erro para a função chamadora
  • catch — Trata o erro localmente
  • if — Verifica se houve erro
// Propagar com try
const dados = try arquivo.read(buffer);

// Tratar com catch
const dados = arquivo.read(buffer) catch |err| {
    std.debug.print("Falhou: {}\n", .{err});
    return;
};

7. O que é um allocator e por que preciso de um?

Em Zig, toda alocação de memória é explícita. Não existe new ou malloc implícito. Você passa um allocator para qualquer função que precisa alocar memória:

const allocator = std.heap.page_allocator;

// Alocar memória
var lista = std.ArrayList(u8).init(allocator);
defer lista.deinit();

try lista.append(42);

Isso torna o código mais previsível e testável. Para iniciantes, std.heap.page_allocator ou std.testing.allocator (em testes) são bons pontos de partida.

8. O que defer faz?

defer executa uma expressão quando a execução sai do escopo atual. É usado principalmente para limpeza de recursos:

const arquivo = try std.fs.cwd().openFile("dados.txt", .{});
defer arquivo.close(); // Fecha quando sair do escopo, não importa como

// ...usar arquivo...
// arquivo.close() será chamado automaticamente aqui

Isso garante que recursos sejam liberados mesmo se ocorrer um erro. É uma das ferramentas mais poderosas do Zig para gerenciar recursos.

9. Como faço um loop em Zig?

Zig tem while e for, mas o for funciona diferente de outras linguagens:

// For sobre slices/arrays
const nums = [_]i32{ 1, 2, 3, 4, 5 };
for (nums) |n| {
    std.debug.print("{d} ", .{n});
}

// For com índice
for (nums, 0..) |n, i| {
    std.debug.print("[{d}]={d} ", .{ i, n });
}

// While
var i: usize = 0;
while (i < 10) : (i += 1) {
    std.debug.print("{d} ", .{i});
}

Zig não tem for (int i = 0; i < 10; i++) como C. O for é exclusivamente para iteração sobre coleções.

10. Qual a diferença entre array e slice?

  • Array tem tamanho fixo conhecido em tempo de compilação: [5]u8
  • Slice é uma referência a uma parte de um array com tamanho conhecido em runtime: []u8
var arr = [_]i32{ 10, 20, 30, 40, 50 };  // array de 5 elementos
const slice: []i32 = arr[1..4];           // slice: { 20, 30, 40 }
std.debug.print("len={d}\n", .{slice.len}); // 3

Slices são usados em toda parte em Zig, especialmente para strings ([]const u8).

11. Strings em Zig são complicadas?

Strings em Zig são simplesmente slices de bytes: []const u8. Não existe um tipo string dedicado. Literais de string são *const [N:0]u8 (ponteiro para array com terminador null):

const saudacao: []const u8 = "Olá, Zig!";
std.debug.print("{s}\n", .{saudacao});
std.debug.print("Tamanho: {d}\n", .{saudacao.len});

Isso pode parecer estranho no início, mas é consistente e eficiente. Para manipulação avançada de strings, use as funções em std.mem e std.fmt.

12. Como crio e uso structs?

Structs são o mecanismo principal de agrupamento de dados em Zig:

const Pessoa = struct {
    nome: []const u8,
    idade: u32,

    pub fn apresentar(self: Pessoa) void {
        std.debug.print("Sou {s}, {d} anos\n", .{ self.nome, self.idade });
    }
};

const maria = Pessoa{ .nome = "Maria", .idade = 30 };
maria.apresentar();

13. Como rodo testes?

Zig tem suporte nativo a testes, sem frameworks externos:

const std = @import("std");
const expect = std.testing.expect;

fn somar(a: i32, b: i32) i32 {
    return a + b;
}

test "somar funciona" {
    try expect(somar(2, 3) == 5);
    try expect(somar(-1, 1) == 0);
}

Execute com zig test arquivo.zig.

14. Onde encontro material para estudar?

15. Errei e o compilador deu um erro enorme. O que faço?

Leia a primeira linha do erro. Zig tem mensagens de erro excelentes que indicam exatamente o arquivo, linha e coluna do problema. Frequentemente, o compilador sugere a correção. Consulte nosso guia de erros de compilação para os erros mais comuns.

Veja Também

Continue aprendendo Zig

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