ProgramlamaGo geliştiricisi

Go'da gömülü fonksiyonlar append, len ve cap nedir, dil seviyesinde nasıl çalışırlar ve bunların kullanımı ile ilgili dilimlerin gizli tehlikeleri nelerdir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

Go'da gömülü fonksiyonlar append, len ve cap, dilimler (slices) ile çalışırken önemli bir rol oynar.

  • len(slice) dilimdeki eleman sayısını döndürür.
  • cap(slice) dilimin kapasitesini döndürür - yeni bellek tahsisi olmadan maksimum eleman sayısını.
  • append(slice, elems ...T) kapasite yetersiz olduğunda yeni bir dizi (ve dolayısıyla yeni bir bellek depolama alanı) oluşturur, bu da dilimin geçiş semantiğini beklenmedik bir şekilde değiştirebilir.

Örnek:

arr := []int{1,2,3} arr2 := append(arr, 4) // arr2, arr'ın kapasitesine bağlı olarak aynı veya yeni bir backing array'de olabilir.

İncelikler:

  • Eğer başka bir dilimden (veya ana diziden) "kesilmiş" bir dilime append yapıyorsanız, olası bir yan etki: orijinal verilerin değiştirilmesi.
  • Dilimleri fonksiyonlara geçirirken len/cap sadece "görünen" kısım üzerinde etkili olur.
  • Eğer append ile cap aşılırsa yeni bir dizi oluşturulur, eskiye dokunulmaz.

Altyazılı Soru

Bir dilimin "kesilmesi" ve append ile bir eleman eklenmesi durumunda ne olur? Bu orijinal dizi üzerinde bir etki yapar mı?

Cevap: Eğer cap uygunsa, append elemanı orijinal dizinin "sonuna" yazar ve değişiklikler aynı diziyi referans alan tüm dilimlerde görünür.

Örnek:

a := []int{1,2,3,4} b := a[:2] // [1 2], len=2, cap=4 b = append(b, 10) // a değişir: a -> [1, 2, 10, 4]

Gerçek Hata Örnekleri


Hikaye

Ekip, alt dilimde elemanlar ekledi ve beklenmedik bir şekilde ana dizideki veriler değişti - bu, iş mantığında uyumsuzluklara ve kullanıcılar arasında görev dağılımında zor hata ayıklama sorunlarına neden oldu.


Hikaye

Büyük bir dilimde append'i tekrar çağırdıklarında, yeni dizinin her zaman yeniden tahsis edileceğini umuyorlardı, ancak gerçekte sistemin birkaç parçası aynı "backing array" ile çalışmaya devam etti ve bu da yarış durumu ve veri bozulmasına yol açtı.


Hikaye

Bir geliştirici, make ile sabit boyutlu bir dilim tahsis etti ama argümanları yer değiştirdi: make([]int, cap, len). Sonuç olarak, kapasiteye dayalı olarak tasarlanan mantık beklenmedik bir şekilde uzunluğa çalıştı ve s[0:len] sınırlarını aşarken panik yarattı.