Dilim bildirmek mi yoksa dilim yapmak mı?


99

Go'da var s []intve arasındaki fark s := make([]int, 0)nedir?

Her ikisinin de işe yaradığını görüyorum ama hangisi daha iyi?


İlki bir nildilim oluşturur , ikincisi ise bir emptydilim oluşturur (bu "Harekete geçme kitabı" tarafından kullanılan terminolojidir ). Aynı cevabı buraya da göndermekten kaçınmak için, stackoverflow.com/a/45997533/1561148
tgogos

Yanıtlar:


95

Ek olarak fabriziom 'ın cevabı , siz 'daha fazla örnek görebilirsiniz : kullanımı ve iç görün Git dilimleri için bir kullanım' []intsöz edilir:

Bir dilimin ( nil) sıfır değeri, sıfır uzunluklu bir dilim gibi davrandığından , bir dilim değişkeni bildirebilir ve ardından ona bir döngü içinde ekleyebilirsiniz:

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

Bu, bir dilime eklemek için önce bellek ayırmanız gerekmediği anlamına gelir: dilim, eklemek için bir nildilim p int[]olarak yeterlidir.


Neden bir tahsisat yapacağını düşünüyorsun? Kapak sıfırdır, bu nedenle make ile veya make olmadan hiçbir şey tahsis edilmez.
Arman Ordookhani

1
@ArmanOrdookhani Kabul Edildi. Beyanı var p []intkullanmaktan daha kolay buluyorum make(ki bunu daha çok ayırmayla ilişkilendiriyorum, 0 sınırı olsa bile hiçbir şey tahsis etmiyor). Okunabilirlik açısından makeburayı kullanmamayı tercih ediyorum .
VonC

1
Ben her yerde değişmez değerleri kullanmaya daha çok meyilliyim (örneğin p := []int{}). :=Çoğu değişkeni bildirmek için genellikle sözdizimi kullandığımızdan , dilimler için istisnalar koymak yerine her yerde bulundurmak daha doğaldır. Bunun dışında tahsisleri düşünmeye çalışmak insanları genellikle erken optimizasyonlara itiyor.
Arman Ordookhani

113

Basit beyan

var s []int

bellek ve ayırmaz spuan nilolurken,

s := make([]int, 0)

hafızayı tahsis eder ve shafızaya 0 elemanlı bir dilime işaret eder.

Kullanım durumunuzun tam boyutunu bilmiyorsanız, genellikle ilki daha deyimseldir.


Harita için de aynısını söyleyebilir miyim? var m eşleme [dize] int ve m: = yapma (eşleme [dize] int)? Teşekkürler.
joshua

11
Hayır, makeharitalara ihtiyacınız var , çünkü boş bir mapyer bile bir miktar muhasebe için ayrılmış alana ihtiyaç duyar.
twotwotwo

11
0 elemanlı bir dilim döndürmeniz gerekiyorsa ('nil' yerine), doğru kullanım yapmaktır.
Jess

6
Bir API oluşturuyorsanız ve yanıt olarak bir dizi döndürüyorsanız, nildiliminizin boş bir dizi yerine herhangi bir öğesi olmaması durumunda bildirim temelli formun kullanılması döndürülür . Bununla birlikte, makedilimi oluşturmak için kullanılırsa, bunun yerine genellikle istenen efekt olan boş bir dizi döndürülür.
robinmitra

6
Bu cevapla ilgili bir yorumda belirtildiği gibi: stackoverflow.com/a/29164565/1311538 , json sıralamak gibi şeyler yapmaya çalışırken farklılıklar vardır. Sıfır dilimi sıralamak ( var s []int) üretecek null, boş dilimi sıralamak ( s := make([]int, 0)) ise beklenen[]
asgaines

8

Sadece bir fark buldum. Eğer kullanırsan

var list []MyObjects

ve sonra çıktıyı JSON olarak kodlarsınız null.

list := make([]MyObjects, 0)

[]beklendiği gibi sonuçlanır .


yah, ikincisi null yerine [] dizi ile yanıt vermek istediğimizde oldukça kullanışlıdır
Nhan Tran

4

Biraz daha eksiksiz (bir argüman daha var make) örnek:

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

Dışarı:

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

Veya dinamik tipte slice:

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

Dışarı:

length:  2 - capacity 5 - content:  [<nil> <nil>]

2
İyi örnekler. +1
VonC
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.