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
Sempre tenha um return final — mesmo que ache que ele nunca será alcançado.
Use early returns — trate erros primeiro, retorne cedo, deixe o happy path no final.
Adicione
defaultem switches — cobre casos inesperados e documenta a intenção.Configure seu editor — gopls mostra este erro em tempo real.
Retorne erros — ao invés de retornar valores mágicos (como -1 ou “”), retorne um
errorexplicando o problema. Veja tratamento de erros.Escreva testes — testes de tabela cobrem múltiplos caminhos e revelam retornos faltantes.
Erros Relacionados
- declared and not used — outra verificação estrita do compilador Go
- cannot use X as type Y — quando o tipo do return está errado
- multiple-value in single-value context — retorno de múltiplos valores
- Tratamento de Erros em Go — padrões de error handling