In Go ist bekannt, dass Methoden mit Zeigerempfängern die ursprünglichen Werte der Variablen, die sie bedienen, beibehalten An. Es scheint jedoch ein offensichtlicher Widerspruch zu bestehen, wenn eine Methode ein Zeigerargument erwartet und ihr ein Nicht-Zeigerwert übergeben wird.
Betrachten Sie den folgenden Ausschnitt für Übung 51 in der Tour of Go:
func (v *Vertex) Scale(f float64) { v.X *= f v.Y *= f } func main() { v := &Vertex{3, 4} v.Scale(2) fmt.Println(v) // Output: &{6 8} }
Der Erklärung zufolge sollte die Scale-Methode v nicht ändern, da sie einen Zeiger auf einen Vertex (*Vertex) anstelle eines Vertex erhält selbst.
Wenn wir jedoch die Zeile v := &Vertex{3, 4} in v := Vertex{3, 4} in main ändern, ändert sich die Ausgabe von &{6 8} zu {6 8 } (beachten Sie das fehlende &). Dies weist darauf hin, dass v geändert wurde, obwohl es als Nicht-Zeigerwert übergeben wurde.
Der Schlüssel liegt in der stark typisierten Natur von Go und den Compileroptimierungen. Auch wenn die Scale-Methode einen Zeigerempfänger erwartet, kann sie dennoch Nicht-Zeigerwerte akzeptieren, da Go diese implizit in Zeiger umwandelt.
Konkret schreibt der Compiler den folgenden Code neu:
v := Vertex{3, 4} v.Scale(2)
zu:
(&v).Scale(2)
Dies bedeutet, dass die Methode tatsächlich mit einem Zeiger auf v aufgerufen wird, wodurch sie das Original ändern kann Wert.
Die folgende Go-spezifische Regel erklärt dieses Verhalten:
Ein Methodenaufruf x.m() ist gültig, wenn der Methodensatz von (der Typ von) x m enthält und die Argumentliste dies kann der Parameterliste von m zugeordnet werden. Wenn x adressierbar ist und der Methodensatz von & sie auf Zeiger, um die Methodentypsicherheit zu wahren.
Das obige ist der detaillierte Inhalt vonWarum ändert eine Go-Methode mit einem Zeigerempfänger ein Nicht-Zeigerargument?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!