Cara yang benar untuk menginisialisasi slice kosong

227

Untuk mendeklarasikan slice kosong, dengan ukuran tidak tetap, apakah lebih baik untuk melakukan:

mySlice1 := make([]int, 0)

atau:

mySlice2 := []int{}

Hanya bertanya-tanya mana yang benar.

butik
sumber
2
Anda mengatakan "ukuran tidak tetap", tetapi irisan tidak pernah memiliki ukuran tetap. Kecuali Anda maksud dengan kapasitas nol. Catatan, jika Anda memiliki ide / tebak / petunjuk tentang kapasitas apa yang mungkin Anda butuhkan maka menggunakan versi tiga argumen itu bagus. Misalnya untuk membangun sepotong kunci peta:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C
1
Kemungkinan duplikat dari Declare slice atau make slice?
pengguna

Jawaban:

272

Dua alternatif yang Anda berikan identik secara semantik, tetapi menggunakan make([]int, 0)akan menghasilkan panggilan internal ke runtime.makeslice (Go 1.14).

Anda juga memiliki opsi untuk memberikan nilnilai:

var myslice []int

Seperti yang tertulis di blog Golang.org :

irisan nil secara fungsional setara dengan irisan panjang-nol, meskipun tidak menunjukkan apa-apa. Panjangnya nol dan dapat ditambahkan, dengan alokasi.

Sebuah nilslice akan tetapi json.Marshal()menjadi "null"sedangkan irisan kosong akan marshal ke"[]" , seperti yang ditunjukkan oleh @farwayer.

Tak satu pun dari opsi di atas akan menyebabkan alokasi apa pun, seperti yang ditunjukkan oleh @ArmanOrdookhani.

Anisus
sumber
4
Juga sebutkan di wiki github.com/golang/go/wiki/…
Grzegorz Żur
106
Hati-hati: json.Marshal()akan kembali nulluntuk var myslice []intdan []untuk potongan yang diinisialisasimyslice := []int{}
farwayer
10
Juga berhati-hati: reflect.DeepEqualmembuat perbedaan antara irisan nihil dan irisan non-nihil: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines
1
Mengapa Anda pikir itu akan melakukan alokasi? Cap adalah nol sehingga tidak ada yang dialokasikan. Semua petunjuk ke titik panjang menunjuk ke lokasi yang sama di memori: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani
1
@ArmanOrdookhani Anda benar. Saya mencobanya, dan saya juga menemukan bahwa saya salah dengan asumsi saya tentang instruksi perakitan yang sama. Tetap!
ANisus
65

Mereka setara. Lihat kode ini:

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

Keluaran:

mySlice1 0
mySlice2 0

Kedua irisan memiliki 0 kapasitas yang berarti kedua irisan memiliki0 panjang (tidak bisa lebih besar dari kapasitas) yang menyiratkan kedua irisan tidak memiliki elemen. Ini berarti 2 irisan identik dalam setiap aspek.

Lihat pertanyaan serupa:

Apa gunanya memiliki potongan nihil dan potongan kosong di golang?

irisan nil vs irisan non-nil vs irisan kosong dalam bahasa Go

icza
sumber
46

Sebagai tambahan untuk @ANisus jawaban ...

di bawah ini adalah beberapa informasi dari "Bertindak" , yang menurut saya layak disebutkan:

Perbedaan antara nil&empty irisan

Jika kita memikirkan irisan seperti ini:

[pointer] [length] [capacity]

kemudian:

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

irisan nil

Mereka berguna ketika Anda ingin mewakili sepotong yang tidak ada, seperti ketika pengecualian terjadi pada fungsi yang mengembalikan sepotong.

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

potongan kosong

Iris kosong berguna ketika Anda ingin merepresentasikan koleksi kosong, seperti ketika kueri basis data mengembalikan hasil nol.

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

Terlepas dari apakah Anda menggunakan sepotong nihil atau irisan kosong, built-in fungsi append, lendan capkerja sama.


Go playground contoh :

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

}

cetakan:

true 0 0
false 0 0
tgogo
sumber
Bisakah kita mendapatkan alamat slice kosong dalam satu langkah menggunakan make?
Simin Jie
Jika kita melihat fungsi tanda tangan , makesepertinya tidak mengembalikan alamat. Saya percaya Anda tidak dapat melakukannya dalam satu langkah.
tgogos
13

Iris kosong dan irisan nil diinisialisasi secara berbeda di 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

Adapun ketiga irisan, len dan cap adalah 0.

Joe.CK
sumber
make([]int, 0)adalah yang terbaik karena Jetbrains GoLand tidak mengeluh tentang hal itu menjadi "tidak perlu" seperti dalam kasus []int{}. Ini berguna dalam penulisan unit test.
Andrzej Rehmann