Introducción: el momento de la verdad para el desarrollador Go
\n\nSi alguna vez has programado en Go (Golang) y has usado interfaces, seguramente te has encontrado con este mensaje del compilador:
\n\ncannot 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\nEn Stack Overflow, esta pregunta acumula miles de visitas. Los principiantes se quedan perplejos, los experimentados se encogen de hombros. Pero en realidad, detrás de este error hay un concepto elegante e importante: la diferencia entre value receiver y pointer receiver en el lenguaje Go.
\n\nEn este artículo, exploraremos «bajo el capó» del compilador Go, analizaremos ejemplos reales de código y entenderemos cómo evitar esta trampa. Aprenderás no solo por qué ocurre el error, sino también cómo se relaciona con el sistema de tipos e interfaces.
\n\n1. Interfaces en Go: breve introducción
\n\nAntes de sumergirnos en el error, recordemos cómo funcionan las interfaces de Go. A diferencia de Java o C++, en Go una interfaz es un conjunto de métodos. Si un tipo implementa todos los métodos de la interfaz, automáticamente satisface esa interfaz (tipado pato).
\n\nEjemplo de una interfaz simple:
\n\ntype Speaker interface {\n Speak() string\n}\n\nAhora definamos una estructura y un método:
\n\ntype Dog struct {\n Name string\n}\n\n// Value receiver — el método trabaja con una copia de la estructura\nfunc (d Dog) Speak() string {\n return "¡Guau! Soy " + d.Name\n}\n\nAquí, Dog implementa Speaker. Funciona tanto con Dog como con *Dog:
var s Speaker\ns = Dog{Name: "Bobby"} // ✅ OK\ns = &Dog{Name: "Rex"} // ✅ OK (Go desreferencia automáticamente)\n\nTodo simple por ahora. Ahora cambiemos el método a pointer receiver:
\n\nfunc (d *Dog) Speak() string {\n return "¡Guau! Soy " + d.Name\n}\n\nY aquí comienza la magia.
\n\n2. Pointer receiver vs Value receiver: ¿cuál es la diferencia?
\n\nEn Go, los métodos pueden tener dos tipos de receptores (receivers):
\n\n- \n
- Value receiver
(t Type)— el método recibe una copia del valor. \n - Pointer receiver
(t *Type)— el método recibe un puntero al valor original. \n
¿Por qué es importante? Porque el conjunto de métodos de un tipo depende del receiver que se utilice.
\n\nTabla de verdad:
\n\n- \n
- El tipo
Ttiene todos los métodos con value receiver (paraT). \n - El tipo
*Ttiene todos los métodos con value receiver + pointer receiver. \n
En otras palabras: el puntero obtiene un «conjunto adicional» de métodos, mientras que el valor solo tiene aquellos declarados con value receiver.
\n\nEsto no es un error, sino una característica del diseño de Go. El compilador no puede tomar automáticamente la dirección de un valor si este no es direccionable (por ejemplo, el resultado de una función o un literal).
\n\n3. Análisis del error: «method has a pointer receiver»
\n\nVolvamos a nuestro ejemplo. Si Speak() está declarado con *Dog, entonces:
var s Speaker\ns = Dog{Name: "Bobby"} // ❌ ERROR\n// cannot use Dog{...} as Speaker...\n// method has a pointer receiver\n\n¿Por qué? Porque Dog (no puntero) no tiene el método Speak() en su conjunto. El método pertenece solo a *Dog.
Pero esto sí funciona:
\n\ns = &Dog{Name: "Bobby"} // ✅ OK\n\nAhora analicemos un ejemplo más realista de código que a menudo se encuentra en Stack Overflow.
\n\nEjemplo: interfaz y estructura con datos
\n\npackage main\n\nimport "fmt"\n\ntype User interface {\n GetID() int\n SetName(name string)\n}\n\ntype Admin struct {\n ID int\