missing return at end of function em Go

O erro “missing return at end of function” aparece quando o compilador do Go detecta que uma função declara valores de retorno, mas nem todos os caminhos de execução terminam com um return. O compilador exige que toda função com retorno declarado retorne um valor em todos os caminhos possíveis.


A Mensagem de Erro

./main.go:12:1: missing return at end of function

Causas Comuns

1. Retorno Apenas dentro de Condição

O caso mais frequente — retornar apenas dentro de um if sem cobrir o else:

package main

func classificar(nota int) string {
    if nota >= 7 {
        return "aprovado"
    }
    if nota >= 5 {
        return "recuperação"
    }
    // ERRO: missing return at end of function
    // E se nota < 5? Nenhum return!
}

2. Switch Sem Default

Um switch sem default não garante cobertura completa:

package main

func diaDaSemana(dia int) string {
    switch dia {
    case 1:
        return "segunda"
    case 2:
        return "terça"
    case 3:
        return "quarta"
    case 4:
        return "quinta"
    case 5:
        return "sexta"
    case 6:
        return "sábado"
    case 7:
        return "domingo"
    }
    // ERRO: missing return at end of function
    // E se dia for 0 ou 8?
}

3. Loop Sem Retorno Garantido

Um loop que pode não executar nenhuma iteração:

package main

func encontrar(nums []int, alvo int) int {
    for _, n := range nums {
        if n == alvo {
            return n
        }
    }
    // ERRO: missing return at end of function
    // E se o alvo não for encontrado?
}

4. Retorno Condicional com Error

Padrão comum ao tratar erros onde se esquece do caminho feliz:

package main

import (
    "fmt"
    "os"
)

func lerArquivo(path string) ([]byte, error) {
    dados, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("erro ao ler: %w", err)
    }
    // ERRO: missing return at end of function
    // Esqueceu de retornar dados quando não há erro!
}

Como Resolver

Solução 1: Adicionar Return Final

A forma mais direta — adicione um retorno padrão no final:

package main

func classificar(nota int) string {
    if nota >= 7 {
        return "aprovado"
    }
    if nota >= 5 {
        return "recuperação"
    }
    return "reprovado" // Cobre todos os outros casos
}

Solução 2: Default no Switch

Adicione um default que cobre todos os casos restantes:

package main

func diaDaSemana(dia int) string {
    switch dia {
    case 1:
        return "segunda"
    case 2:
        return "terça"
    case 3:
        return "quarta"
    case 4:
        return "quinta"
    case 5:
        return "sexta"
    case 6:
        return "sábado"
    case 7:
        return "domingo"
    default:
        return "dia inválido"
    }
}

Solução 3: Retorno Após o Loop

Trate o caso em que o loop não encontra o resultado:

package main

import "errors"

func encontrar(nums []int, alvo int) (int, error) {
    for _, n := range nums {
        if n == alvo {
            return n, nil
        }
    }
    return 0, errors.New("valor não encontrado")
}

Solução 4: Completar Todos os Caminhos

Garanta que tanto o caminho de sucesso quanto o de erro retornem:

package main

import (
    "fmt"
    "os"
)

func lerArquivo(path string) ([]byte, error) {
    dados, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("erro ao ler: %w", err)
    }
    return dados, nil // Caminho de sucesso
}

Solução 5: Named Returns

Retornos nomeados podem simplificar funções complexas, mas use com moderação:

package main

import "fmt"

func dividir(a, b float64) (resultado float64, err error) {
    if b == 0 {
        err = fmt.Errorf("divisão por zero")
        return // Retorna os named returns com seus valores atuais
    }
    resultado = a / b
    return // resultado = a/b, err = nil
}

Solução 6: Panic para Casos Impossíveis

Quando você sabe que certo caminho é logicamente impossível, use panic:

package main

type Cor int

const (
    Vermelho Cor = iota
    Verde
    Azul
)

func nomeCor(c Cor) string {
    switch c {
    case Vermelho:
        return "vermelho"
    case Verde:
        return "verde"
    case Azul:
        return "azul"
    }
    panic(fmt.Sprintf("cor desconhecida: %d", c))
}

Padrão Idiomático: Early Return

O estilo idiomático do Go favorece “early returns” — retornar cedo nos casos de erro e deixar o caminho feliz sem indentação:

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Config struct {
    Host string `json:"host"`
    Port int    `json:"port"`
}

func carregarConfig(path string) (*Config, error) {
    dados, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("leitura: %w", err)
    }

    var cfg Config
    if err := json.Unmarshal(dados, &cfg); err != nil {
        return nil, fmt.Errorf("parse JSON: %w", err)
    }

    if cfg.Port == 0 {
        return nil, fmt.Errorf("porta não configurada")
    }

    return &cfg, nil // Caminho feliz, sem indentação extra
}

Esse padrão é detalhado no guia de tratamento de erros em Go e nas boas práticas do Go.


Dicas para Evitar Este Erro

  1. Sempre tenha um return final — mesmo que ache que ele nunca será alcançado.

  2. Use early returns — trate erros primeiro, retorne cedo, deixe o happy path no final.

  3. Adicione default em switches — cobre casos inesperados e documenta a intenção.

  4. Configure seu editorgopls mostra este erro em tempo real.

  5. Retorne erros — ao invés de retornar valores mágicos (como -1 ou “”), retorne um error explicando o problema. Veja tratamento de erros.

  6. Escreva testestestes de tabela cobrem múltiplos caminhos e revelam retornos faltantes.


Erros Relacionados