«X does not implement Y»: analisando o erro com pointer receiver em Go

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: o momento da verdade para o desenvolvedor Go

\n\n

Se você já escreveu em Go (Golang) e usou interfaces, certamente já encontrou esta mensagem do compilador:

\n\n
cannot use x (variable of type *MyStruct) as type MyInterface value in assignment:\n*MyStruct does not implement MyInterface (method GetName has a pointer receiver)
\n\n

No Stack Overflow, esta pergunta acumula milhares de visualizações. Iniciantes ficam perplexos, experientes — encolhem os ombros. Mas, na verdade, por trás deste erro existe um conceito elegante e importante: a diferença entre value receiver e pointer receiver na linguagem Go.

\n\n

Neste artigo, vamos olhar «sob o capô» do compilador Go, analisar exemplos reais de código e entender como evitar essa armadilha. Você aprenderá não apenas por que o erro ocorre, mas também como ele se relaciona com o sistema de tipos e interfaces.

\n\n

1. Interfaces em Go: um breve resumo

\n\n

Antes de mergulharmos no erro, vamos relembrar como funcionam as interfaces Go. Diferente de Java ou C++, em Go uma interface é um conjunto de métodos. Se um tipo implementa todos os métodos da interface, ele automaticamente satisfaz essa interface (duck typing).

\n\n

Exemplo de uma interface simples:

\n\n
type Speaker interface {\n    Speak() string\n}
\n\n

Agora vamos definir uma struct e um método:

\n\n
type Dog struct {\n    Name string\n}\n\n// Value receiver — o método trabalha com uma cópia da struct\nfunc (d Dog) Speak() string {\n    return "Au! Eu sou " + d.Name\n}
\n\n

Aqui, Dog implementa Speaker. Funciona tanto com Dog quanto com *Dog:

\n\n
var s Speaker\ns = Dog{Name: "Bobby"}  // ✅ OK\ns = &Dog{Name: "Rex"}  // ✅ OK (Go desreferencia automaticamente)
\n\n

Até aqui, tudo simples. Agora vamos mudar o método para pointer receiver:

\n\n
func (d *Dog) Speak() string {\n    return "Au! Eu sou " + d.Name\n}
\n\n

E aí começa a mágica.

\n\n

2. Pointer receiver vs Value receiver: qual a diferença?

\n\n

Em Go, os métodos podem ter dois tipos de receptores (receivers):

\n\n
    \n
  • Value receiver (t Type) — o método recebe uma cópia do valor.
  • \n
  • Pointer receiver (t *Type) — o método recebe um ponteiro para o valor original.
  • \n
\n\n

Por que isso é importante? Porque o conjunto de métodos de um tipo depende de qual receiver é usado.

\n\n

Tabela verdade:

\n\n
    \n
  • O tipo T possui todos os métodos com value receiver (para T).
  • \n
  • O tipo *T possui todos os métodos com value receiver + pointer receiver.
  • \n
\n\n

Em outras palavras: o ponteiro recebe um «conjunto bônus» de métodos, enquanto o valor tem apenas aqueles declarados com value receiver.

\n\n

Isso não é um bug, mas uma característica do design do Go. O compilador não pode pegar automaticamente o endereço de um valor se ele não for endereçável (por exemplo, resultado de uma função ou literal).

\n\n

3. Análise do erro: «method has a pointer receiver»

\n\n

Voltemos ao nosso exemplo. Se Speak() for declarado com *Dog, então:

\n\n
var s Speaker\ns = Dog{Name: "Bobby"}  // ❌ ERRO\n// cannot use Dog{...} as Speaker...\n// method has a pointer receiver
\n\n

Por quê? Porque Dog (não ponteiro) não possui o método Speak() em seu conjunto. O método pertence apenas a *Dog.

\n\n

Já isso funciona:

\n\n
s = &Dog{Name: "Bobby"}  // ✅ OK
\n\n

Agora vamos analisar um exemplo mais realista de código, frequentemente encontrado no Stack Overflow.

\n\n

Exemplo: interface e struct com dados

\n\n
package main\n\nimport "fmt"\n\ntype User interface {\n    GetID() int\n    SetName(name string)\n}\n\ntype Admin struct {\n    ID   int\                

Blogs

Book Recommendations