2016-04-27 4 views
1
anotherSlice := theSlice 
anotherSlice = append(anotherSlice, newEle) 
fmt.Println(len(anotherSlice) == len(theSlice)) 

Dieses Snippet gibt false aus. Warum?Eine Variable vom Referenztyp "Slice" einer anderen Variablen zuweisen, warum ändern sie sich nicht gleichzeitig?

Und hier sind einige andere Experimente:

package main 

import "fmt" 

func main() { 
    theSlice := []int{3,3,2,5,12,43} 
    anotherSlice := theSlice 
    fmt.Println(anotherSlice[3], theSlice[3]) 
    anotherSlice[3] = anotherSlice[3]+2 
    fmt.Println(anotherSlice[3], theSlice[3]) 
    anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...) 
    fmt.Println(len(anotherSlice),len(theSlice)) 
} 

Der Ausgang wie unten:

5 5 
7 7 
5 6 

Program exited. 

Antwort

2

Wenn hängten Scheibe anotherSlice keinen Platz für das neue Element hat, schafft append Funktion neue Scheibe und kehrt es. Seitdem sind die Schichten anotherSlice und theSlice unterschiedlich - sie werden durch separate Arrays unterstützt.

Das Auflösen einer Schicht mit einer kürzeren Länge anotherSlice[:3] hat keinen Einfluss auf die ursprüngliche Kapazität der Schicht.

die folgende Zeile:

anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...) 

schneidet vierte (Index 3) Element. Da anotherSlice[:3] über die Kapazität verfügt, alle Elemente von anotherSlice[4:] zu speichern, tritt keine neue Zuweisung auf und daher werden beide Segmente geändert.

package main 

import (
     "fmt" 
) 

func main() { 
     x := []int{1, 2, 3, 4, 5, 6} 
     fmt.Println(cap(x[:3]) >= len(x[:3])+len(x[4:])) 
     y := append(x[:3], x[4:]...) 
     fmt.Println(x, y) 
} 

Playground

+0

Ich versuchte etwas anderes, um die Länge zu schrumpfen, der Prozess wird in der Post aktualisiert. Ist das so, weil "anotherSlice" nach dem Schrumpfen auch die Kapazität auf 5 reduziert hat? –

1

Die Antwort, warum die Länge einer Scheibe nicht den Wechsel zu einer anderen Scheibe der Längenänderung folgen nicht verwandt mit dem zugrunde liegenden Speicher p önologisch kopiert und/oder modifiziert werden.

In Go ist es wichtig sich zu erinnern, was eine Scheibe ist. Es ist eine Struktur mit einem Längenfeld, einem Kapazitätsfeld und einem Zeiger auf ein Array. Einige Operationen ändern das Längenfeld. Einige ändern das Kapazitätsfeld. Einige ändern die Daten, die im zugrunde liegenden Array gespeichert sind.

Wenn man nicht versteht, wie ein Slice in der Sprache implementiert wird, wird es alle Arten von Verwirrung und Fehlern geben und Chancen verschenken. Sobald man sich daran gewöhnt hat, wie ein Slice implementiert wird, sind sie sehr einfach zu verwenden und die Tatsache, dass der Compiler die Struktur des Slices versteht, kann geschrieben werden, wobei sehr eleganter und leicht lesbarer Code geschrieben werden kann.

Verwandte Themen