Einleitung: Der Moment der Wahrheit für Go-Entwickler
\n\nWenn Sie jemals in Go (Golang) programmiert und Interfaces verwendet haben, sind Sie sicherlich auf diese Compiler-Meldung gestoßen:
\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\nAuf Stack Overflow erhält diese Frage tausende Aufrufe. Anfänger sind verwirrt, erfahrene zucken mit den Schultern. Aber hinter diesem Fehler steckt ein elegantes und wichtiges Konzept: der Unterschied zwischen value receiver und pointer receiver in der Sprache Go.
\n\nIn diesem Artikel werfen wir einen Blick «unter die Haube» des Go-Compilers, analysieren echte Codebeispiele und verstehen, wie man diese Falle vermeidet. Sie erfahren nicht nur warum der Fehler auftritt, sondern auch wie er mit dem Typ- und Interface-System zusammenhängt.
\n\n1. Interfaces in Go: Kurze Einführung
\n\nBevor wir in den Fehler eintauchen, erinnern wir uns daran, wie Go-Interfaces funktionieren. Im Gegensatz zu Java oder C++ ist ein Interface in Go eine Menge von Methoden. Wenn ein Typ alle Methoden eines Interfaces implementiert, erfüllt er dieses Interface automatisch (Ententypisierung).
\n\nBeispiel eines einfachen Interfaces:
\n\ntype Speaker interface {\n Speak() string\n}\n\nJetzt definieren wir eine Struktur und eine Methode:
\n\ntype Dog struct {\n Name string\n}\n\n// Value receiver – die Methode arbeitet mit einer Kopie der Struktur\nfunc (d Dog) Speak() string {\n return "Wuff! Ich bin " + d.Name\n}\n\nHier implementiert Dog das Interface Speaker. Es funktioniert sowohl mit Dog als auch mit *Dog:
var s Speaker\ns = Dog{Name: "Bello"} // ✅ OK\ns = &Dog{Name: "Rex"} // ✅ OK (Go dereferenziert automatisch)\n\nBisher alles einfach. Ändern wir nun die Methode auf einen pointer receiver:
\n\nfunc (d *Dog) Speak() string {\n return "Wuff! Ich bin " + d.Name\n}\n\nUnd hier beginnt die Magie.
\n\n2. Pointer receiver vs Value receiver: Was ist der Unterschied?
\n\nIn Go können Methoden zwei Arten von Empfängern (receivers) haben:
\n\n- \n
- Value receiver
(t Type)– die Methode erhält eine Kopie des Werts. \n - Pointer receiver
(t *Type)– die Methode erhält einen Zeiger auf den ursprünglichen Wert. \n
Warum ist das wichtig? Weil der Methodensatz eines Typs davon abhängt, welcher receiver verwendet wird.
\n\nWahrheitstabelle:
\n\n- \n
- Der Typ
That alle Methoden mit value receiver (fürT). \n - Der Typ
*That alle Methoden mit value receiver + pointer receiver. \n
Mit anderen Worten: Der Zeiger erhält einen «Bonus»-Methodensatz, während der Wert nur die Methoden hat, die mit value receiver deklariert sind.
\n\nDas ist kein Bug, sondern ein Feature des Go-Designs. Der Compiler kann nicht automatisch die Adresse eines Werts nehmen, wenn dieser nicht adressierbar ist (z. B. das Ergebnis einer Funktion oder ein Literal).
\n\n3. Analyse des Fehlers: «method has a pointer receiver»
\n\nKehren wir zu unserem Beispiel zurück. Wenn Speak() mit *Dog deklariert ist, dann:
var s Speaker\ns = Dog{Name: "Bello"} // ❌ FEHLER\n// cannot use Dog{...} as Speaker...\n// method has a pointer receiver\n\nWarum? Weil Dog (kein Zeiger) die Methode Speak() nicht in seinem Methodensatz hat. Die Methode gehört nur zu *Dog.
Das hingegen funktioniert:
\n\ns = &Dog{Name: "Bello"} // ✅ OK\n\nJetzt analysieren wir ein praxisnäheres Beispiel aus echtem Code, das oft auf Stack Overflow zu finden ist.
\n\nBeispiel: Interface und Struktur mit Daten
\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\