Empfänger und Schnittstelle
Methoden mit Wertempfängern können sowohl mit Werten als auch mit Zeigern aufgerufen werden.
Methoden mit Zeigerempfängern können nur mit Zeigern oder adressierbaren Werten aufgerufen werden.
Beispiel:
type S struct {
data string
}
func (s S) Read() string {
return s.data
}
func (s *S) Write(str string) {
s.data = str
}
sVals := map[int]S{1: {"A"}}
// Sie können Read nur mit einem Wert aufrufen
sVals[1].Read()
// Dies wird nicht kompilieren:
// sVals[1].Write("test")
sPtrs := map[int]*S{1: {"A"}}
// Sowohl Read als auch Write Methoden können mit einem Zeiger aufgerufen werden
sPtrs[1].Read()
sPtrs[1].Write("test")
Ebenso kann eine Methode, auch wenn sie einen Wertempfänger hat, eine Schnittstelle mithilfe eines Zeigerempfängers erfüllen.
type F interface {
f()
}
type S1 struct{}
func (s S1) f() {}
type S2 struct{}
func (s *S2) f() {}
s1Val := S1{}
s1Ptr := &S1{}
s2Val := S2{}
s2Ptr := &S2{}
var i F
i = s1Val
i = s1Ptr
i = s2Ptr
// Der folgende Code wird nicht kompilieren, da s2Val ein Wert ist und die Methode f von S2 keinen Wertempfänger hat
// i = s2Val
Effective Go enthält ausgezeichnete Erklärungen zu Zeigern vs. Werten.
Zusätzliche Hinweise:
- Ein Typ kann einen Methodensatz mit Wertempfängern und einen Methodensatz mit Zeigerempfängern haben.
- Der Methodensatz mit Wertempfängern ist ein Untermenge des Methodensatzes mit Zeigerempfängern, aber nicht umgekehrt.
- Regeln
- Wertobjekte können nur den Methodensatz mit Wertempfängern verwenden.
- Zeigerobjekte können den Methodensatz mit Wertempfängern + den Methodensatz mit Zeigerempfängern verwenden.
- Schnittstellenanpassung (oder Implementierung)
- Der Typ passt zur Schnittstelle, wenn er alle Methoden der Schnittstelle implementiert.
- Genauer gesagt, passt entweder der Wertmethodensatz des Typs zur Schnittstelle oder der Zeigermethodensatz passt zur Schnittstelle.
Es gibt zwei spezifische Arten des Anpassens:
- Wertmethodensatz passt zur Schnittstelle
- Es ist in Ordnung, einem Wert oder einem Zeigerobjekt eine Schnittstellenvariable zuzuweisen, da beide den Wertmethodensatz enthalten.
- Zeigermethodensatz passt zur Schnittstelle
- Nur ein Zeigerobjekt kann einer Schnittstellenvariable zugewiesen werden, da nur der Zeigermethodensatz zur Schnittstelle passt.
- Wenn einem Wertobjekt eine Schnittstellenvariable zugewiesen wird, wird während der Kompilierung ein Mechanismus zur Überprüfung der Schnittstellenaktualität ausgelöst.
Warum i = s2Val einen Fehler auslöst, liegt daran, dass der Wertmethodensatz und die Schnittstelle nicht übereinstimmen.