Cheatsheet: Controle de Fluxo em Zig
Referência completa para todas as estruturas de controle de fluxo em Zig, incluindo padrões avançados com optionals e error unions.
If / Else
// If básico
if (condicao) {
// código
}
// If / else
if (x > 0) {
std.debug.print("positivo\n", .{});
} else if (x < 0) {
std.debug.print("negativo\n", .{});
} else {
std.debug.print("zero\n", .{});
}
// If como expressão
const abs = if (x >= 0) x else -x;
// If com captura de optional
var talvez: ?i32 = 42;
if (talvez) |valor| {
std.debug.print("Valor: {}\n", .{valor});
} else {
std.debug.print("É null\n", .{});
}
// If com captura de ponteiro (para modificar)
if (talvez) |*ptr| {
ptr.* += 1;
}
// If com error union
const resultado: anyerror!i32 = calcular();
if (resultado) |valor| {
std.debug.print("Ok: {}\n", .{valor});
} else |err| {
std.debug.print("Erro: {}\n", .{err});
}
Switch
// Switch básico
const x: i32 = 5;
switch (x) {
1 => std.debug.print("um\n", .{}),
2, 3 => std.debug.print("dois ou três\n", .{}),
4...10 => std.debug.print("entre 4 e 10\n", .{}),
else => std.debug.print("outro\n", .{}),
}
// Switch como expressão
const texto = switch (x) {
1 => "um",
2 => "dois",
else => "outro",
};
// Switch com enum
const Cor = enum { vermelho, verde, azul };
const cor: Cor = .verde;
switch (cor) {
.vermelho => doVermelho(),
.verde => doVerde(),
.azul => doAzul(),
}
// Switch em enum é exaustivo — não precisa de else se cobrir todos os casos
// Switch com tagged union
const Valor = union(enum) {
inteiro: i64,
texto: []const u8,
nenhum: void,
};
const v = Valor{ .inteiro = 42 };
switch (v) {
.inteiro => |i| std.debug.print("Int: {}\n", .{i}),
.texto => |t| std.debug.print("Texto: {s}\n", .{t}),
.nenhum => std.debug.print("Nenhum\n", .{}),
}
// Switch com captura de ponteiro
var valor: u8 = 5;
switch (valor) {
3...7 => |*v| {
v.* = 0; // modificar o valor original
},
else => {},
}
// Switch com múltiplos ranges
switch (char) {
'a'...'z' => handleMinuscula(char),
'A'...'Z' => handleMaiuscula(char),
'0'...'9' => handleDigito(char),
else => handleOutro(char),
}
While
// While básico
var i: u32 = 0;
while (i < 10) {
std.debug.print("{} ", .{i});
i += 1;
}
// While com continue expression (como "increment" do for em C)
var j: u32 = 0;
while (j < 10) : (j += 1) {
std.debug.print("{} ", .{j});
}
// While com captura de optional
var it = iterador();
while (it.next()) |item| {
processarItem(item);
}
// While com else (executa quando condição é falsa)
var k: u32 = 0;
const resultado = while (k < 10) : (k += 1) {
if (k == 5) break k;
} else blk: {
break :blk @as(u32, 0); // valor se nenhum break foi executado
};
// While com captura de erro
while (leitor.readByte()) |byte| {
processarByte(byte);
} else |err| {
if (err != error.EndOfStream) return err;
}
// While infinito
while (true) {
// loop infinito — use break para sair
if (deveSair()) break;
}
For
// For sobre array/slice
const arr = [_]i32{ 1, 2, 3, 4, 5 };
for (arr) |valor| {
std.debug.print("{} ", .{valor});
}
// For com índice
for (arr, 0..) |valor, i| {
std.debug.print("[{}]={} ", .{ i, valor });
}
// For com ponteiro (para modificar)
var mut = [_]i32{ 1, 2, 3 };
for (&mut) |*elem| {
elem.* *= 2;
}
// For sobre múltiplos arrays
const nomes = [_][]const u8{ "Ana", "Bruno", "Carlos" };
const idades = [_]u32{ 25, 30, 35 };
for (nomes, idades) |nome, idade| {
std.debug.print("{s} tem {} anos\n", .{ nome, idade });
}
// For com range
for (0..10) |i| {
std.debug.print("{} ", .{i});
}
// For como expressão (com break)
const encontrado = for (arr) |valor| {
if (valor == 3) break valor;
} else @as(i32, -1);
Break e Continue
// Break — sair do loop
for (0..100) |i| {
if (i == 50) break;
std.debug.print("{} ", .{i});
}
// Continue — pular para próxima iteração
for (0..10) |i| {
if (i % 2 == 0) continue; // pular pares
std.debug.print("{} ", .{i}); // só ímpares
}
// Break com valor (loop como expressão)
const resultado = for (arr) |valor| {
if (valor > 3) break valor;
} else @as(i32, 0);
// Break nomeado — sair de loop externo
outer: for (0..10) |i| {
for (0..10) |j| {
if (i * j > 30) break :outer;
std.debug.print("({},{})", .{ i, j });
}
}
// Continue nomeado
outer: for (0..10) |i| {
for (0..10) |j| {
if (j % 2 == 0) continue :outer;
_ = i;
}
}
Blocos Nomeados
// Bloco nomeado com valor de retorno
const resultado = blk: {
var acumulador: i32 = 0;
for (arr) |valor| {
acumulador += valor;
}
break :blk acumulador;
};
// Blocos nomeados para escape de loops aninhados
const pos = outer: for (matrix, 0..) |linha, i| {
for (linha, 0..) |valor, j| {
if (valor == alvo) break :outer .{ i, j };
}
} else .{ @as(usize, 0), @as(usize, 0) };
Padrões com Optionals
// Encadeamento de optionals
const config = getConfig();
const valor = if (config) |c|
if (c.secao) |s|
s.chave
else
null
else
null;
// orelse para valor padrão
const seguro = getOptional() orelse valorPadrao;
// orelse com bloco
const resultado = getOptional() orelse blk: {
std.log.warn("Usando fallback\n", .{});
break :blk calcularFallback();
};
// orelse unreachable (assert que não é null)
const garantido = getOptional() orelse unreachable;
Padrões com Erros
// try — propagar erro
const valor = try funcaoQuePoderFalhar();
// catch — tratar erro
const valor2 = funcaoQuePoderFalhar() catch |err| {
std.log.err("Falha: {}\n", .{err});
return err;
};
// catch com valor padrão
const valor3 = funcaoQuePoderFalhar() catch 0;
// switch no erro
funcaoQuePoderFalhar() catch |err| switch (err) {
error.ArquivoNaoEncontrado => {
std.log.warn("Arquivo não existe\n", .{});
},
error.PermissaoNegada => {
std.log.err("Sem permissão\n", .{});
return err;
},
else => return err,
};
Tabela de Referência
| Estrutura | Uso |
|---|---|
if (cond) expr | Condicional simples |
if (opt) |v| expr | Desempacotar optional |
if (err_union) |v| expr else |e| expr | Desempacotar error union |
switch (val) { ... } | Seleção múltipla |
while (cond) expr | Loop com condição |
while (cond) : (inc) expr | Loop com incremento |
for (slice) |elem| expr | Iteração sobre coleção |
for (slice, 0..) |e, i| expr | Iteração com índice |
for (0..n) |i| expr | Range loop |
break | Sair do loop |
break :label valor | Sair com valor |
continue | Próxima iteração |
Veja Também
- Sintaxe Básica — Operadores e expressões
- Error Handling — Tratamento de erros em detalhes
- Funções — Funções e closures
- Padrão State Machine — Máquinas de estado com switch
- Padrão Iterator — Implementando iteradores