Go'daki map ve slice yapılarının kopyalama ve bellek ile çalışma semantikaları, deneyimsiz geliştiricilerde sıklıkla beklenmedik davranışlara yol açan önemli özelliklere sahiptir.
Go, statik tipli ve varsayılan olarak işaretçi eksikliği olan katı bir dil olarak kabul edilse de, map ve slice için özel bir iç model uygulanmıştır: her iki tür de referans yapılarıdır. Bu, kopyalama ve bu nesnelerin geçirilmesi ile ilgili çok sayıda nüans yaratmakta ve kısıtlamalara neden olmaktadır.
Map ve slice kopyalama işlemleri içeriğin derin kopyasını oluşturmaz; bunun yerine aynı nesneye yeni bir referans oluşturur. Bu, veri değiştirilirken, fonksiyonlardan değerlerin yanlış döndürülmesi ve modifikasyonlar sırasında beklenmedik yan etkilere yol açar. Ayrıca, bir fonksiyondan map veya slice döndürmek, ek tahsisatlara veya bellek sızıntılarına neden olabilir.
b := a[:]). Elemanların tam olarak kopyalanması için yerleşik copy() fonksiyonu kullanılmalıdır.Doğru kopyalama örneği:
// Slice kopyalama a := []int{1, 2, 3} b := make([]int, len(a)) copy(b, a) // b artık a'dan bağımsız // Map kopyalama src := map[string]int{"x": 1} dst := make(map[string]int) for k, v := range src { dst[k] = v }
Anahtar özellikler:
slice ve map referans tiplerdir, içerik değil tanımlayıcı üzerinden kopyalanırBir map/slice'i diğerine atayıp, sonra birini değiştirirsek ne olur?
Her iki map ve slice, bellekte aynı verilere işaret edecek: değişiklik her iki nesneyi de etkileyecektir.
Fonksiyonlardan slice veya map döndürmenin neden "bellek açısından verimli" olduğu sıkça söylenir?
Çünkü, tüm içeriğin değil, tanımlayıcının bir kopyası döndürülür; yığın bellek üzerindeki veriler, onlara referans olduğu sürece yaşamaya devam eder.
copy() fonksiyonunu kullanarak map'in "derin" kopyasını yapabilir miyiz?
Hayır, copy() yalnızca slice ve diziler için çalışır; map için her zaman bir döngü gereklidir.
Bir geliştirici, kopyalamayı önlemek için slice veya map'i atama ile kopyalar ve kopyayı değiştirir:
Artıları:
Eksileri:
Gerekli verilerin modifikasyonundan önce slice için copy() ve map için döngü kullanılır:
Artıları:
Eksileri: