Das Anhängen von Slice und seine Auswirkung auf das ursprüngliche Slice verstehen
Beim Arbeiten mit Slices in Go wird die Append-Funktion häufig zum Anhängen neuer Elemente verwendet zu einem vorhandenen Slice. Viele Entwickler werden jedoch überrascht sein, wenn sie feststellen, dass dieser Anhängevorgang auch das Original-Slice ändern kann.
Der untersuchte Code
Bedenken Sie den folgenden Codeausschnitt:
func someFunc(A []int) int { for i := 0; i < len(A); i++ { tempA := A // copy the slice by value fmt.Println("A: ", A) fmt.Println("tempA: ", A) fmt.Println() newArr = remove(tempA, i) if isAesthetic(newArr) { ways++ } } } func remove(slice []int, s int) []int { return append(slice[:s], slice[s+1:]...) }
Hier nimmt die someFunc-Funktion ein Slice A als Eingabe und erstellt dann eine Kopie von A namens tempA, bevor sie die aufruft Remove-Funktion zum Entfernen eines Elements aus tempA. Wenn Sie die Funktion in Aktion untersuchen, bemerken Sie möglicherweise die folgende Konsolenausgabe:
A: [3 4 5 3 7] tempA: [3 4 5 3 7] A: [4 5 3 7 7] tempA: [4 5 3 7 7] A: [4 3 7 7 7] tempA: [4 3 7 7 7] A: [4 3 7 7 7] tempA: [4 3 7 7 7]
Der überraschende Nebeneffekt
Während der Code ausgeführt wird, wird der Inhalt von gedruckt Sowohl A als auch tempA, was zeigt, dass der ursprüngliche Slice A ebenfalls geändert wird, nachdem append für tempA aufgerufen wurde. Dieses Verhalten mag auf den ersten Blick kontraintuitiv erscheinen, da man erwarten würde, dass eine By-Value-Kopie von A unabhängig von allen an tempA vorgenommenen Änderungen ist.
Dieses Phänomen ist jedoch eine direkte Folge der Art und Weise, wie Slices implementiert werden in Go. Slices sind im Wesentlichen eine leichtgewichtige Datenstruktur, die aus einem Header und einem Zeiger auf das zugrunde liegende Array besteht. Der Header enthält Informationen über die Länge und Kapazität des Slice, während der Zeiger auf das erste Element im Slice zeigt.
Wenn Sie tempA den Wert von A zuweisen, erstellen Sie im Wesentlichen einen neuen Slice-Header, der auf zeigt das gleiche zugrunde liegende Array wie A. Daher werden alle an tempA vorgenommenen Änderungen auch in A widergespiegelt, da beide Slices auf dieselben Daten verweisen.
Slice verstehen Header und Arrays
Um dieses Verhalten besser zu verstehen, ist es hilfreich zu verstehen, wie Slice-Header und Arrays in Go interagieren. Ein Array enthält einen zusammenhängenden Block von Elementen desselben Typs. Ein Slice hingegen bietet eine dynamische Ansicht eines Abschnitts des Arrays. Es beschreibt einen aufeinanderfolgenden Satz von Elementen innerhalb des Arrays, besitzt aber nicht die zugrunde liegenden Array-Daten.
Wenn Sie ein Slice aus einem Array mit der Syntax []T{e1, e2, ... erstellen, en} erstellen Sie im Wesentlichen einen neuen Slice-Header, der auf das erste Element im Array zeigt. Die Länge des Slice wird auf n und die Kapazität auf die verbleibende Länge des Arrays nach dem Slice festgelegt.
Ähnlich gilt, wenn Sie einen Slice-Header mit der Syntax []T(arr) erstellen, Sie erstellen ein Slice, das auf dasselbe zugrunde liegende Array wie arr verweist. Die Länge des Slice wird auf die Länge von arr und die Kapazität auf die Kapazität von arr eingestellt.
Implikationen und Best Practices
Wenn Sie die Beziehung zwischen Slices und Arrays verstehen, können Sie potenzielle Fallstricke vermeiden und effizienteren Go-Code schreiben. Beachten Sie beim Arbeiten mit Slices Folgendes:
Wenn Sie die Interna von Go-Slices verstehen, können Sie deren Flexibilität und Effizienz nutzen und gleichzeitig sicherstellen, dass sich Ihr Code wie beabsichtigt verhält. Indem Sie die Nuancen von Slice-Headern und -Arrays nutzen, können Sie die Kunst des Slicings in Go meistern und das volle Potenzial dieser vielseitigen Datenstruktur ausschöpfen.
Das obige ist der detaillierte Inhalt vonWarum verändert das Anhängen an eine Kopie eines Go-Slices auch das Original-Slice?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!