multiple-value in single-value context em Go
O erro “multiple-value X() (untyped nil, error) in single-value context” aparece quando você tenta usar o resultado de uma função que retorna múltiplos valores em um contexto que espera apenas um valor. Em Go, funções frequentemente retornam dois ou mais valores (especialmente o padrão (valor, error)), e o compilador exige que você trate todos eles.
A Mensagem de Erro
./main.go:10:7: multiple-value os.Open() (untyped nil, error) used in single-value context
./main.go:15:12: multiple-value strconv.Atoi() (int, error) used in single-value context
Causas Comuns
1. Atribuição Simples de Função com Dois Retornos
O caso mais comum — tentar capturar o resultado em uma única variável:
package main
import "os"
func main() {
// ERRO: os.Open retorna (*File, error)
file := os.Open("config.json")
_ = file
}
2. Usar Multi-Return Diretamente em Expressão
Tentar usar o retorno diretamente em uma chamada de função ou expressão:
package main
import (
"fmt"
"strconv"
)
func main() {
// ERRO: strconv.Atoi retorna (int, error)
fmt.Println(strconv.Atoi("42"))
}
Nota: Na verdade, fmt.Println aceita ...interface{}, então este caso específico compila! Mas outros contextos não:
package main
import "strconv"
func dobro(n int) int {
return n * 2
}
func main() {
// ERRO: strconv.Atoi retorna (int, error), dobro espera apenas int
resultado := dobro(strconv.Atoi("42"))
_ = resultado
}
3. Passando Multi-Return como Argumento
Funções que recebem um único argumento não aceitam multi-return:
package main
import (
"os"
"io"
)
func processar(r io.Reader) {
// ...
}
func main() {
// ERRO: os.Open retorna (*os.File, error)
processar(os.Open("dados.txt"))
}
4. Atribuição em Struct Literal ou Map
Multi-return não funciona em inicializações inline:
package main
import "strconv"
type Config struct {
Port int
}
func main() {
// ERRO: strconv.Atoi retorna (int, error)
cfg := Config{
Port: strconv.Atoi("8080"),
}
_ = cfg
}
Como Resolver
Solução 1: Capturar Todos os Valores de Retorno
A forma idiomática em Go — capture tudo e trate o erro:
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("config.json")
if err != nil {
fmt.Println("Erro:", err)
return
}
defer file.Close()
fmt.Println("Arquivo aberto:", file.Name())
}
Solução 2: Descartar Valores com _
Se você tem certeza de que não precisa de um valor, use o identificador em branco:
package main
import (
"fmt"
"strconv"
)
func main() {
// Descarta o erro (CUIDADO: só faça isso quando for seguro!)
valor, _ := strconv.Atoi("42")
fmt.Println(valor) // 42
}
Aviso: Descartar erros com _ é geralmente uma má prática. Só faça quando o erro é logicamente impossível (como converter uma constante string conhecida).
Solução 3: Variável Intermediária
Quando precisa usar o resultado em uma expressão:
package main
import (
"fmt"
"strconv"
)
func dobro(n int) int {
return n * 2
}
func main() {
// Primeiro captura
n, err := strconv.Atoi("42")
if err != nil {
fmt.Println("Erro:", err)
return
}
// Depois usa
resultado := dobro(n)
fmt.Println(resultado) // 84
}
Solução 4: Criar Helper para Ignorar Erro
Para conversões em constantes ou inicializações de pacote, crie um helper must:
package main
import (
"fmt"
"strconv"
)
// must panics se err != nil — use apenas com valores constantes
func must[T any](val T, err error) T {
if err != nil {
panic(err)
}
return val
}
func main() {
// Seguro: "8080" é uma constante válida
port := must(strconv.Atoi("8080"))
fmt.Println("Porta:", port)
}
A partir do Go 1.18 com generics, o pattern must funciona com qualquer tipo. Funções Must já existem na stdlib, como template.Must e regexp.MustCompile.
Solução 5: Inicialização em Duas Etapas
Para structs e maps:
package main
import (
"fmt"
"strconv"
)
type Config struct {
Port int
}
func main() {
port, err := strconv.Atoi("8080")
if err != nil {
fmt.Println("Porta inválida:", err)
return
}
cfg := Config{
Port: port,
}
fmt.Printf("Porta: %d\n", cfg.Port)
}
Por Que Go Faz Assim?
Go exige que você lide com todos os valores de retorno por design. Isso:
- Força o tratamento de erros — você não pode “esquecer” que uma função pode falhar
- Torna o fluxo explícito — cada possibilidade de falha é visível no código
- Evita bugs silenciosos — diferente de exceções, erros não são ignorados sem que você deliberadamente use
_
Essa filosofia é detalhada em por que aprender Go e no guia de tratamento de erros.
Dicas para Evitar Este Erro
Sempre capture todos os retornos — o padrão
valor, err := funcao()é onipresente em Go.Trate erros imediatamente — use
if err != nillogo após a chamada. Veja boas práticas de erros.Use
mustpara constantes — crie helpers com generics para valores que sabidamente não falham.Configure o gopls — seu editor mostrará o erro antes de compilar.
Nunca descarte erros em produção —
_, _ = funcao()esconde bugs. Use logging estruturado para registrar erros.
Erros Relacionados
- missing return at end of function — quando uma função não retorna em todos os caminhos
- declared and not used — variáveis de retorno capturadas mas não usadas
- cannot use X as type Y — quando o tipo do retorno não é compatível
- Tratamento de Erros em Go — guia completo de error handling