---
title: "expected return expression — Como Resolver em Zig"
url: "https://ziglang.com.br/erros/expected-return-expression-como-resolver-em-zig/"
markdown_url: "https://ziglang.com.br/erros/expected-return-expression-como-resolver-em-zig.MD"
description: "Entenda o erro 'expected return expression' em Zig, que ocorre quando uma função deve retornar um valor mas não possui return explícito."
date: "2026-02-21"
author: "Zig Brasil"
---

# expected return expression — Como Resolver em Zig

Entenda o erro 'expected return expression' em Zig, que ocorre quando uma função deve retornar um valor mas não possui return explícito.


# expected return expression — Como Resolver em Zig

## O Que Este Erro Significa

O erro `expected return expression` ocorre quando uma função em Zig declara um tipo de retorno diferente de `void`, mas o compilador detecta que existe um caminho de execução que termina sem uma expressão `return` adequada. Zig exige que todas as funções com tipo de retorno não-void retornem explicitamente um valor em todos os caminhos possíveis.

## Causas Comuns

### 1. Função Sem Return

```zig
fn calcular(x: i32) i32 {
    const resultado = x * 2;
    // ERRO: função termina sem return
    _ = resultado;
}
```

### 2. Return Apenas em Alguns Branches

```zig
fn classificar(n: i32) []const u8 {
    if (n > 0) {
        return "positivo";
    } else if (n < 0) {
        return "negativo";
    }
    // ERRO: e se n == 0? Não há return para esse caso
}
```

### 3. Switch Sem Cobertura Completa

```zig
const Cor = enum { vermelho, verde, azul };

fn nomeCor(c: Cor) []const u8 {
    switch (c) {
        .vermelho => return "vermelho",
        .verde => return "verde",
        // ERRO: falta o caso .azul
    }
}
```

### 4. Loop que Pode Não Executar

```zig
fn encontrar(arr: []const u32, alvo: u32) u32 {
    for (arr) |item| {
        if (item == alvo) return item;
    }
    // ERRO: e se o array estiver vazio ou o item não for encontrado?
}
```

### 5. Confundir void com Tipo de Retorno

```zig
fn processar(dados: []const u8) []const u8 {
    if (dados.len == 0) {
        return; // ERRO: return sem valor em função que retorna []const u8
    }
    return dados;
}
```

## Como Corrigir

### Solução 1: Adicionar Return Explícito

```zig
fn calcular(x: i32) i32 {
    const resultado = x * 2;
    return resultado; // Correto: retorna o valor
}
```

### Solução 2: Cobrir Todos os Branches

```zig
fn classificar(n: i32) []const u8 {
    if (n > 0) {
        return "positivo";
    } else if (n < 0) {
        return "negativo";
    } else {
        return "zero"; // Correto: todos os caminhos cobertos
    }
}
```

### Solução 3: Usar else em Switch

```zig
const Cor = enum { vermelho, verde, azul };

fn nomeCor(c: Cor) []const u8 {
    return switch (c) {
        .vermelho => "vermelho",
        .verde => "verde",
        .azul => "azul", // Correto: todos os casos cobertos
    };
}
```

Se você quer garantir exaustividade sem usar `else`:

```zig
fn nomeCor(c: Cor) []const u8 {
    return switch (c) {
        .vermelho => "vermelho",
        .verde => "verde",
        .azul => "azul",
        // Se um novo valor for adicionado ao enum, este switch
        // dará erro de compilação — forçando você a tratá-lo
    };
}
```

### Solução 4: Adicionar Return Após Loop

```zig
fn encontrar(arr: []const u32, alvo: u32) ?u32 {
    for (arr) |item| {
        if (item == alvo) return item;
    }
    return null; // Correto: retorna null se não encontrado
}
```

Ou usando error:

```zig
const BuscaError = error{NaoEncontrado};

fn encontrar(arr: []const u32, alvo: u32) BuscaError!u32 {
    for (arr) |item| {
        if (item == alvo) return item;
    }
    return BuscaError.NaoEncontrado;
}
```

### Solução 5: Usar unreachable Quando Apropriado

Se você tem certeza absoluta de que um caminho nunca será alcançado:

```zig
fn dividir(a: u32, b: u32) u32 {
    if (b != 0) {
        return a / b;
    }
    unreachable; // Você garante que b nunca será 0
}
```

**Cuidado**: `unreachable` causa comportamento indefinido se for alcançado. Use apenas quando realmente puder garantir que o caminho é impossível.

## Padrões Recomendados

### Expressão Switch Como Retorno

Em vez de `return` em cada braço, use switch como expressão:

```zig
fn obterPrioridade(nivel: u8) []const u8 {
    return switch (nivel) {
        0 => "baixa",
        1 => "média",
        2 => "alta",
        3 => "crítica",
        else => "desconhecida",
    };
}
```

### Expressão if Como Retorno

```zig
fn absoluto(n: i32) u32 {
    return if (n >= 0) @intCast(n) else @intCast(-n);
}
```

### Retorno Antecipado (Early Return)

O padrão de retorno antecipado é idiomático em Zig:

```zig
fn processar(dados: ?[]const u8) []const u8 {
    const d = dados orelse return "vazio"; // Retorno antecipado
    if (d.len == 0) return "vazio";
    return d;
}
```

## Diferença Entre void e noreturn

- `void`: A função não retorna nenhum valor, mas retorna o controle ao chamador
- `noreturn`: A função nunca retorna (ex: loop infinito, @panic, exit)

```zig
fn saudacao() void {
    // OK sem return — tipo de retorno é void
    std.debug.print("Olá!\n", .{});
}

fn falhar() noreturn {
    @panic("erro fatal"); // Nunca retorna
}
```

## Erros Relacionados

- [unreachable code](/erros/erro-unreachable-code/) — Código após return que nunca executa
- [expected expression](/erros/erro-expected-expression/) — Expressão esperada pelo compilador
- [expected type 'X', found 'Y'](/erros/erro-expected-type/) — Tipo de retorno incompatível

## Links Úteis

- [Documentação oficial do Zig — Functions](https://ziglang.org/documentation/master/#Functions)
- [Zig Language Reference — Control Flow](https://ziglang.org/documentation/master/#Control-Flow)
