Prawidłowy sposób inicjowania pustego plasterka

227

Aby zadeklarować pusty plasterek o nieokreślonym rozmiarze, lepiej zrobić:

mySlice1 := make([]int, 0)

lub:

mySlice2 := []int{}

Zastanawiam się tylko, który z nich jest właściwy.

eouti
źródło
2
Mówisz „nieokreślony rozmiar”, ale plastry nigdy nie mają ustalonego rozmiaru. Chyba że masz na myśli zerową pojemność. Uwaga: jeśli masz pomysł / zgadnij / podpowiedź, jakiej pojemności możesz potrzebować, to użycie wersji z trzema argumentami jest dobre. Np. Żeby zbudować kawałek kluczy do mapy:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C
1
Możliwy duplikat Deklaracji wycinka lub zrób wycinek?
użytkownik

Odpowiedzi:

272

Dwie podane alternatywy są semantycznie identyczne, ale użycie make([]int, 0)spowoduje wewnętrzne wywołanie runtime.makeslice (Go 1.14).

Możesz też pozostawić nilwartość:

var myslice []int

Jak napisano na blogu Golang.org :

wycinek zerowy jest funkcjonalnie równoważny wycinku zerowej długości, nawet jeśli nie wskazuje na nic. Ma długość zero i może być dołączony wraz z alokacją.

nilPlaster będzie jednak json.Marshal()pod "null"natomiast pusty plaster będzie zebrać się "[]", jak podkreślił @farwayer.

Żadna z powyższych opcji nie spowoduje przydziału, jak wskazał @ArmanOrdookhani.

ANisus
źródło
4
Wspomnij także na wiki github.com/golang/go/wiki/…
Grzegorz Żur
106
Zachowaj ostrożność: json.Marshal()wróci nullpo zainicjowany plasterek var myslice []inti []na niegomyslice := []int{}
farwayer
10
Ponadto należy zachować ostrożność: reflect.DeepEqualrozróżnia zerowe plastry i plastry nie zerowe: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines
1
Dlaczego uważasz, że to przydział? Limit wynosi zero, więc nic nie jest przydzielane. Wszystkie wskaźniki zerowej długości wskazują na to samo miejsce w pamięci: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani
1
@ArmanOrdookhani Masz rację. Wypróbowałem to i dowiedziałem się, że mylę się z moim założeniem dotyczącym identycznych instrukcji montażu. Naprawiony!
ANisus
65

Są równoważne. Zobacz ten kod:

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

Wynik:

mySlice1 0
mySlice2 0

Oba wycinki mają 0pojemność, co oznacza, że ​​oba wycinki mają 0długość (nie może być większa niż pojemność), co oznacza, że ​​oba wycinki nie mają elementów. Oznacza to, że 2 plastry są identyczne pod każdym względem.

Zobacz podobne pytania:

Po co mieć zero i pusty kawałek w Golang?

zero plasterków vs non-zero plasterków vs puste plasterki w języku Go

icza
źródło
46

Jako dodatek do odpowiedzi @ANisus ...

poniżej znajduje się kilka informacji z książki „Go in action” , o której moim zdaniem warto wspomnieć:

Różnica między nil& emptyplasterkami

Jeśli pomyślimy o takim kawałku:

[pointer] [length] [capacity]

następnie:

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

zero plasterka

Są przydatne, gdy chcesz reprezentować plasterek, który nie istnieje, na przykład gdy występuje wyjątek w funkcji zwracającej plasterek.

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

pusty plasterek

Puste wycinki są przydatne, gdy chcesz reprezentować pustą kolekcję, na przykład gdy zapytanie do bazy danych zwraca zero wyników.

// 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{}

Niezależnie od tego, czy używasz nil plasterek lub pusty plaster, z wbudowanymi funkcjami append, leni capdziałają tak samo.


Przykład placu zabaw :

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))

}

drukuje:

true 0 0
false 0 0
tgogos
źródło
Czy możemy uzyskać adres pustego plasterka w jednym kroku za pomocą make?
Simin Jie,
Jeśli spojrzymy na podpis funkcji , makewydaje się , że nie zwraca adresu. Wierzę, że nie możesz tego zrobić jednym krokiem.
tgogos
13

Pusty wycinek i zerowy wycinek są różnie inicjowane w 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

Tak jak w przypadku wszystkich trzech plasterków, długość i czapka wynoszą 0.

Joe.CK
źródło
make([]int, 0)jest najlepszy, ponieważ Jetbrains GoLand nie narzeka, że ​​jest „niepotrzebny”, jak to ma miejsce w przypadku []int{}. Jest to przydatne podczas pisania testów jednostkowych.
Andrzej Rehmann,