2016-07-25 14 views
4

Ich habe eine Frage über den Code untenKapazität der Scheiben in Go

package main 

import "fmt" 

func main() { 
    var a []int 
    printSlice("a", a) 

    // append works on nil slices. 
    a = append(a, 0) 
    printSlice("a", a) 

    // the slice grows as needed. 
    a = append(a, 1) 
    printSlice("a", a) 

    // we can add more than one element at a time. 
    a = append(a, 2, 3, 4) 
    printSlice("a", a) 
} 

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

ich immer raten, was das Ergebnis ein Stück Code ausgeführt aussehen wird dann den Code ausführen und überprüfen, ob meine Vermutung richtig ist. Aber dieser Code resultierte ein wenig anders als meine Vermutung:

Ergebnis:
auf meinem lokalen go Tour Server:

a len=0 cap=0 [] 
a len=1 cap=1 [0] 
a len=2 cap=2 [0 1] 
a len=5 cap=6 [0 1 2 3 4]  

Alles ist in Ordnung, bis die letzte Zeile, aber ich don ‚t erhalten

cap=6  

warum nicht

Meine Meinung ist, dass ich keinen Slice mit expliziter Kapazität erstellt habe, daher gab mein System diesen Wert .

) Aber wenn ich diesen gleichen Code auf dem golang Tour-Server versucht, erhalte ich ein wenig mehr diffferent Ergebnis wie folgt aus:

a len=0 cap=0 [] 
a len=1 cap=2 [0] 
a len=2 cap=2 [0 1] 
a len=5 cap=8 [0 1 2 3 4] 

Was cap = 2 in der zweiten Zeile und cap = 8 auf der letzten Zeile?

+7

Verwenden Sie dieselbe Version wie der Tourserver? Wie "append" die Kapazität erweitert, ist nicht durch die Sprachspezifikation definiert, und die Implementierung kann sich ändern. – JimB

+0

Hmm Ich habe das herausgefunden, wenn ich Elemente an den Slice anfüge, die nicht über die Kapazität der alten Slice-Kapazität hinwegkommen, ändert sich nicht, aber wenn sie die Kapazität übersteigt, ordnet sie den Slice neu an. –

+1

Nun, ich würde sagen, go versucht, Ihre Kapazität ein wenig mehr als Ihr Längenwert zu erhöhen, wenn Länge, und wenn Sie das Limit der Kapazität überschreiten, indem Sie einen neuen Wert hinzufügen, fügt es ein Vielfaches von 2 zum Kapazitätswert, und so endet immer mit einer geraden Zahl, um den Kopierbetrieb zu reduzieren. Dies ist mit Go-Version 1.6 –

Antwort

10

Diese Frage ist kein exaktes Duplikat, aber meine Antwort here beantwortet dies auch effektiv.

TL; DR - wie stark die Kapazität des Slice erweitert wird, wird in der Spezifikation nicht erwähnt und verschiedene Versionen von Go (oder andere Implementierungen oder die gleiche Version auf verschiedenen Architekturen usw.) können den Slice erweitern um verschiedene Beträge.

Der Grund, warum Sie die Kapazität möglicherweise größer als Sie benötigen, ist, weil unterhalb der Scheibe ein Array ist, das unveränderlich ist (es kann nicht erweitert werden). Wenn Sie einen Slice "wachsen", geschieht das tatsächlich, dass Sie ein neues (längeres) Array erstellen, alle Werte kopieren und dann als Backing-Array für das Slice festlegen. Wenn Sie viele Werte anhängen würden, müssten Sie viele und viele Kopien erstellen (eine für jeden einzelnen Wert), was sehr langsam wäre, sodass die Laufzeit stattdessen mehr Speicherplatz zuweist, als Sie für nötig halten Kopien weniger oft erstellen.

+0

gute Erklärung, aber ich denke, die Frage ist mehr darauf konzentriert, warum man ein anderes Ergebnis auf ihrer lokalen Maschine bekommen würde dann den gleichen Code in der Tour Spielplatz laufen. Golang Versionsausgabe ??? – GregL83

+1

Siehe den ersten Abschnitt meiner Antwort; Dies könnte sich aus vielen Gründen ändern.Ich bin mir nicht sicher, ob der spezifische Grund von Bedeutung ist, aber Sie könnten es immer gegen den Spielplatz testen und lokal dieselbe Version, um es einzugrenzen. (FWIW Ich sehe das gleiche Verhalten gerade jetzt, wenn ich zu 1.8 zurückwechsle, was der Spielplatz ist, also ist es nicht die Version). –