2012-10-07 10 views
15

I hat vor kurzem die Go holen, und jetzt verwirrte ich mit dem folgenden Code:Re-Schneiden Scheiben in Golang

package main 

import "fmt" 

func main() { 
    a := make([]int, 5) 
    printSlice("a", a) 
    b := make([]int, 0, 5) 
    printSlice("b", b) 
    c := b[:2] 
    printSlice("c", c) 
    d := c[2:5] 
    printSlice("d", d) 
} 

func printSlice(s string, x []int) { 
    fmt.Printf("%s len=%d cap=%d %v\n", 
     s, len(x), cap(x), x) 
} 

Und das Ergebnis:

a len=5 cap=5 [0 0 0 0 0] 
b len=0 cap=5 [] 
c len=2 cap=5 [0 0] //why the capacity of c not 2 but 5 instead 
d len=3 cap=3 [0 0 0] 

Jede mögliche Hilfe danke.

+0

Scheiben mit ihrer eigenen Kapazität kommen (gehen 1,2). Siehe [meine Antwort unten] (http://stackoverflow.com/a/18911267/6309) – VonC

Antwort

20

c ist ein Schnitt aus dem Array b. Dies ist keine Kopie, sondern nur ein Fenster über die ersten beiden Elemente von b.

Da b eine Kapazität von 5 hat, c könnte erweitert werden, um die 3 anderen Orte zu nehmen (in der Tat macht es eine neue Scheibe aber über den gleichen Ort im Speicher).

Die maximale Kapazität der Scheibe ist die Kapazität des darunterliegenden Array minus die Position des Beginns der Scheibe in der Anordnung:

array : [0 0 0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 
slice :  [0 0 0 0] 
slice :  <---- capacity ---> 

Vielleicht dieses Programm deutlich mehr machen wird, dass c und d nur Fenster über b:

func main() { 
    b := make([]int, 0, 5) 
    c := b[:2] 
    d := c[1:5] // this is equivalent to d := b[1:5] 
    d[0] = 1 
    printSlice("c", c) 
    printSlice("d", d) 
} 

Ausgang:

c len=2 cap=5 [0 1] // modifying d has modified c 
d len=4 cap=4 [1 0 0 0] 
+2

Danke für die hilfreiche Antwort. – Coder

+1

Also wird das b auch Auswirkungen haben? – Coder

+1

Ja. Aber Sie werden es nicht sehen, weil die Länge 0 ist. –

11

Beachten Sie, dass in Gehen Sie 1.2 (Q4 2013, 1.2rc1 is available now), Sie können eine Schicht eine eigene Kapazität zuordnen (anstelle einer Kapazität von dem zugrunde liegenden Array abgeleitet).

Siehe "Three-index slices" und die design document.

Ein Schneidvorgang erzeugt einen neuen Scheibe durch einen zusammenhängenden Abschnitt eines bereits erstellten Array oder slice beschreiben:

var array [10]int 
slice := array[2:4] 

Die Kapazität der Scheibe die maximale Anzahl von Elementen ist, dass die Scheibe kann halten, selbst nach dem Wiederauflösen; Es spiegelt die Größe des zugrunde liegenden Arrays wider.
In diesem Beispiel ist die Kapazität der slice variable 8.

(Kapazität des darunterliegenden Array minus die Position des Beginns der Scheibe in dem Array)

array : [0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 
slice : [0 0] 
slice : <-- capacity --> 8 (10-2) 

Go 1.2 fügt eine neue Syntax hinzu, um einen Slicing-Vorgang auf zu ermöglichen, der die Kapazität sowie die Länge angibt.
Ein zweiter Doppelpunkt führt den Kapazitätswert ein, der kleiner oder gleich der Kapazität der Ausgangsschicht oder des Arrays sein muss, die für den Ursprung angepasst wurde.

Zum Beispiel

slice = array[2:4:6] 

array : [0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 10 
slice : [0 0] 
slice : <- cap->   4 (6-2) 

setzt die Scheibe die gleiche Länge wie in dem früheren Beispiel haben, aber seine Kapazität ist jetzt nur noch 4 Elemente (6-2).
Es ist unmöglich, diesen neuen Schichtwert zu verwenden, um auf die letzten beiden Elemente des ursprünglichen Arrays zuzugreifen.

Das Hauptargument ist Programmierer mehr Kontrolle über append zu geben.

a[i : j : k] 

Das Stück hat:

  • Indizes bei 0
  • Länge beginnend gleich zu j - i
  • Kapazität gleich zu k - i

Die Auswertung gerät in Panik, wenn i <= j <= k <= cap(a) nicht wahr ist.