Modo corretto per inizializzare la sezione vuota


227

Per dichiarare una sezione vuota, con una dimensione non fissa, è meglio fare:

mySlice1 := make([]int, 0)

o:

mySlice2 := []int{}

Mi chiedo solo quale sia il modo corretto.


2
Dici "dimensione non fissa", ma le sezioni non hanno mai una dimensione fissa. A meno che tu non intenda con capacità zero. Nota, se hai un'idea / indovinare / un indizio di quale capacità potresti aver bisogno, allora usare la versione a tre argomenti è buono. Ad esempio per costruire una fetta di chiavi della mappa:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C

1
Possibile duplicato di Dichiara fetta o crea fetta?
utente

Risposte:


272

Le due alternative che hai fornito sono semanticamente identiche, ma l'utilizzo make([]int, 0)comporterà una chiamata interna a runtime.makeslice (Go 1.14).

Hai anche la possibilità di lasciarlo con un nilvalore:

var myslice []int

Come scritto nel blog Golang.org :

una sezione zero è funzionalmente equivalente a una sezione di lunghezza zero, anche se non punta a nulla. Ha lunghezza zero e può essere aggiunto, con allocazione.

Una nilfetta sarà comunque json.Marshal()in "null"mentre una fetta vuoto mobiliterà in"[]" , come fuori punte da @farwayer.

Nessuna delle opzioni di cui sopra provocherà alcuna allocazione, come sottolineato da @ArmanOrdookhani.


4
Anche menzione su wiki github.com/golang/go/wiki/…
Grzegorz Żur

106
Attenzione: json.Marshal()tornerà nullper var myslice []inte []per lo slice inizializzatomyslice := []int{}
Farwayer

10
Anche stare attenti: reflect.DeepEqualfa una distinzione tra le fette e fette nil non nil: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines

1
Perché pensi che farebbe un'allocazione? Il limite è zero, quindi non viene assegnato nulla. Tutti i puntatori a cose di lunghezza zero indicano la stessa posizione in memoria: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani

1
@ArmanOrdookhani Hai ragione. L'ho provato e ho anche scoperto che mi sbagliavo con la mia ipotesi su istruzioni di montaggio identiche. Fisso!
ANisus,

65

Sono equivalenti. Vedi questo codice:

mySlice1 := make([]int, 0)
mySlice2 := []int{}
fmt.Println("mySlice1", cap(mySlice1))
fmt.Println("mySlice2", cap(mySlice2))

Produzione:

mySlice1 0
mySlice2 0

Entrambe le sezioni hanno una 0capacità che implica che entrambe le sezioni0 lunghezza (non può essere maggiore della capacità), il che implica che entrambe le sezioni non hanno elementi. Ciò significa che le 2 sezioni sono identiche in ogni aspetto.

Vedi domande simili:

Qual è il punto di avere una fetta zero e una fetta vuota in Golang?

sezioni zero vs sezioni non zero vs sezioni vuote nella lingua Go


46

In aggiunta a @ANisus ' risposta ...

di seguito sono riportate alcune informazioni dal "Go in action" libro , che credo valga la pena menzionare:

Differenza tra nil&empty slice

Se pensiamo a una fetta come questa:

[pointer] [length] [capacity]

poi:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // points to an address

fetta zero

Sono utili quando si desidera rappresentare una sezione che non esiste, ad esempio quando si verifica un'eccezione in una funzione che restituisce una sezione.

// Create a nil slice of integers.
var slice []int

fetta vuota

Le sezioni vuote sono utili quando si desidera rappresentare una raccolta vuota, ad esempio quando una query del database restituisce risultati zero.

// Use make to create an empty slice of integers.
slice := make([]int, 0)

// Use a slice literal to create an empty slice of integers.
slice := []int{}

Indipendentemente dal fatto che si sta utilizzando una fetta nullo o una fetta di vuoto, il built-in funzioni append, lene capil lavoro lo stesso.


Vai esempio parco giochi :

package main

import (
    "fmt"
)

func main() {

    var nil_slice []int
    var empty_slice = []int{}

    fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
    fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))

}

stampe:

true 0 0
false 0 0

Possiamo ottenere l'indirizzo della sezione vuota in un solo passaggio usando make?
Simin Jie,

Se diamo un'occhiata alla firma della funzione , makenon sembra restituire l'indirizzo. Credo che non puoi farlo in un solo passaggio.
tgogos,

13

La sezione vuota e la sezione zero sono inizializzate diversamente in Go:

var nilSlice []int 
emptySlice1 := make([]int, 0)
emptySlice2 := []int{}

fmt.Println(nilSlice == nil)    // true
fmt.Println(emptySlice1 == nil) // false
fmt.Println(emptySlice2 == nil) // false

Come per tutte e tre le sezioni, len e cap sono 0.


make([]int, 0)è il migliore perché Jetbrains GoLand non si lamenta che sia "non necessario" come nel caso di []int{}. Questo è utile per scrivere unit test.
Andrzej Rehmann,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.