Slice deklarieren oder Slice machen?

98

Was ist in Golang der Unterschied zwischen var s []intund s := make([]int, 0)?

Ich finde, dass beide funktionieren, aber welches ist besser?

Wang Yi
quelle
Der erste erstellt ein nilSlice, während der zweite ein emptySlice erstellt (dies ist die Terminologie, die im "Go in Action Book" verwendet wird ). Um zu vermeiden, dass die gleiche Antwort auch hier veröffentlicht wird, können Sie stackoverflow.com/a/45997533/1561148
tgogos

Antworten:

94

Neben fabriziom ‚s Antwort , können Sie weitere Beispiele zu‚sehen : Nutzung und Interna Go Slices , wo eine Verwendung für‘ []interwähnt wird :

Da sich der Nullwert eines Slice ( nil) wie ein Slice mit der Länge Null verhält , können Sie eine Slice-Variable deklarieren und dann in einer Schleife an sie anhängen:

// Filter returns a new slice holding only
// the elements of s that satisfy f()
func Filter(s []int, fn func(int) bool) []int {
    var p []int // == nil
    for _, v := range s {
        if fn(v) {
            p = append(p, v)
        }
    }
    return p
}

Dies bedeutet, dass Sie zum Anhängen an ein Slice nicht zuerst Speicher zuweisen müssen: Das nilSlice p int[]reicht als Slice zum Hinzufügen aus.

VonC
quelle
Warum denkst du, würde es eine Allokation machen? Cap ist Null, daher wird nichts mit oder ohne make zugewiesen.
Arman Ordookhani
1
@ArmanOrdookhani Einverstanden. Ich finde die Deklaration var p []inteinfach einfacher als die Verwendung make(was ich eher mit der Zuweisung verbinde, obwohl sie mit einer Obergrenze von 0 nichts zuordnen würde). In Bezug auf die Lesbarkeit bevorzuge ich es, makehier nicht zu verwenden .
VonC
Ich benutze eher Literale überall (zB p := []int{}). Da wir normalerweise die :=Syntax verwenden, um die meisten Variablen zu deklarieren, ist es natürlicher, sie überall zu haben, anstatt Ausnahmen für Slices zu haben. Abgesehen davon treiben Versuche, an Zuordnungen zu denken, die Leute normalerweise zu vorzeitigen Optimierungen.
Arman Ordookhani
113

Einfache Erklärung

var s []int

weist keinen Speicher zu und szeigt auf nil, während

s := make([]int, 0)

Ordnet Speicher zu und szeigt auf Speicher auf ein Slice mit 0 Elementen.

Normalerweise ist der erste idiomatischer, wenn Sie die genaue Größe Ihres Anwendungsfalls nicht kennen.

fabrizioM
quelle
Kann ich das auch für die Karte sagen? var m map [string] int vs m: = make (map [string] int)? Vielen Dank.
Joshua
11
Nein, Sie müssen makeKarten erstellen, da selbst ein leerer mapSpeicherplatz für die Buchhaltung benötigt wird.
Zwei
11
Wenn Sie ein Slice mit 0 Elementen (anstelle von 'nil') zurückgeben müssen, ist make die richtige Verwendung.
Jess
6
Wenn Sie eine API erstellen und ein Array als Antwort zurückgeben, wird die Verwendung des deklarativen Formulars zurückgegeben, nilfalls Ihr Slice kein Element und kein leeres Array enthält. Wenn makejedoch zum Erstellen des Slice verwendet wird, wird stattdessen ein leeres Array zurückgegeben, was im Allgemeinen der gewünschte Effekt ist.
Robinmitra
6
Wie in einem Kommentar zu dieser Antwort erwähnt: stackoverflow.com/a/29164565/1311538 , gibt es Unterschiede beim Versuch, Dinge wie JSON-Marshalling zu tun. Marschieren der Nullscheibe (var s []int ) wird produzieren null, während das Marshalling der leeren Slice ( s := make([]int, 0)) die erwarteten[]
Asgaines
8

Habe gerade einen Unterschied gefunden. Wenn du benutzt

var list []MyObjects

und dann codieren Sie die Ausgabe als JSON, erhalten Sie null.

list := make([]MyObjects, 0)

Ergebnisse []wie erwartet.

Steve Hanov
quelle
yah, letzteres ist sehr nützlich, wenn wir mit [] array statt null antworten wollen
Nhan Tran
4

Ein bisschen vollständiger (ein weiteres Argument in make) Beispiel:

slice := make([]int, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

Aus:

length:  2 - capacity 5 - content:  [0 0]

Oder mit dynamischer Art von slice:

slice := make([]interface{}, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

Aus:

length:  2 - capacity 5 - content:  [<nil> <nil>]
Benyamin Jafari
quelle
2
Gute Beispiele. +1
VonC