Nyatakan irisan atau buat irisan?

99

Di Go, apa perbedaan antara var s []intdan s := make([]int, 0)?

Saya menemukan bahwa keduanya berfungsi, tetapi mana yang lebih baik?

Wang Yi
sumber
Yang pertama membuat nilirisan, sedangkan yang kedua membuat emptyirisan (ini adalah terminologi yang digunakan oleh "Go in action book" ). Untuk menghindari memposting jawaban yang sama di sini juga, Anda dapat memeriksa stackoverflow.com/a/45997533/1561148
tgogos

Jawaban:

95

Selain fabriziom 's jawaban , Anda dapat melihat lebih banyak contoh di ' Go Slices: penggunaan dan internal ', di mana penggunaan untuk []intdisebutkan:

Karena nilai nol dari sebuah slice ( nil) bertindak seperti potongan dengan panjang nol , Anda dapat mendeklarasikan variabel slice dan kemudian menambahkannya ke dalam satu putaran:

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

Artinya, untuk menambahkan potongan, Anda tidak harus mengalokasikan memori terlebih dahulu: nilpotongan p int[]tersebut sudah cukup sebagai potongan untuk ditambahkan.

VonC
sumber
Menurut Anda mengapa itu akan melakukan alokasi? Cap adalah nol jadi tidak ada yang dialokasikan dengan atau tanpa make.
Arman Ordookhani
1
@ArOrdookhani Setuju. Saya hanya menemukan deklarasi var p []intlebih mudah daripada menggunakan make(yang lebih saya asosiasikan dengan alokasi, meskipun dengan 0 tutup, itu tidak akan mengalokasikan apa pun). Dalam hal keterbacaan, saya lebih suka tidak menggunakan di makesini.
VonC
1
Saya lebih ke arah penggunaan literal di mana-mana (misalnya p := []int{}). Karena kami biasanya menggunakan :=sintaks untuk mendeklarasikan sebagian besar variabel, lebih alami untuk memilikinya di mana-mana daripada memiliki pengecualian untuk irisan. Selain itu, mencoba memikirkan alokasi biasanya mendorong orang ke pengoptimalan prematur.
Arman Ordookhani
113

Deklarasi sederhana

var s []int

tidak mengalokasikan memori dan smenunjuk ke nil, sementara

s := make([]int, 0)

mengalokasikan memori dan smenunjuk ke memori ke potongan dengan 0 elemen.

Biasanya, yang pertama lebih idiomatis jika Anda tidak mengetahui ukuran pasti kasus penggunaan Anda.

fabrizioM
sumber
Bisakah saya mengatakan hal yang sama untuk peta? var m map [string] int vs m: = make (map [string] int)? Terima kasih.
joshua
11
Nah, Anda perlu makepeta, karena bahkan ruang kosong pun mapperlu dialokasikan untuk beberapa pembukuan.
dua kali
11
Jika Anda perlu mengembalikan slice dengan 0 elemen (bukan 'nil'), make adalah penggunaan yang benar.
Jess
6
Jika Anda membuat API dan mengembalikan array sebagai respons, menggunakan formulir deklaratif akan muncul niljika slice Anda tidak memiliki elemen apa pun, bukan array kosong. Namun, jika makedigunakan untuk membuat potongan, array kosong akan dikembalikan, yang umumnya merupakan efek yang diinginkan.
robinmitra
6
Seperti yang disebutkan dalam komentar pada jawaban ini: stackoverflow.com/a/29164565/1311538 , terdapat perbedaan saat mencoba melakukan hal-hal seperti json marshaling. Mengawetkan irisan nil ( var s []int) akan menghasilkan null, sementara menyusun irisan kosong ( s := make([]int, 0)) akan menghasilkan yang diharapkan[]
lagi
8

Baru saja menemukan perbedaan. Jika Anda menggunakan

var list []MyObjects

dan kemudian Anda mengenkode keluaran sebagai JSON, Anda dapatkan null.

list := make([]MyObjects, 0)

menghasilkan []seperti yang diharapkan.

Steve Hanov
sumber
yah, yang terakhir ini cukup berguna ketika kita ingin merespons dengan array [] daripada null
Nhan Tran
4

Sedikit lebih lengkap (satu argumen lagi make) contoh:

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

Di luar:

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

Atau dengan tipe dinamis slice:

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

Di luar:

length:  2 - capacity 5 - content:  [<nil> <nil>]
Benyamin Jafari
sumber
2
Contoh yang bagus. +1
VonC