Go'da yapılar değer ile (ilk seviyede derin kopyalama), iç içe yapılar aynı kuralla kopyalanır; dilimler ise değer ile kopyalanır, ancak yalnızca yapı kopyalanır, verileri içeren dizi değil: hem orijinal hem de kopya dilim, aynı alt diziye işaret eder, bu nedenle bir dilim üzerinden yapılan değişiklikler diğerini etkiler, eğer dizinin açık bir kopyasını copy() ile yapmazsanız.
Dilim kopyalama örneği:
s1 := []int{1,2,3} s2 := s1 // aynı tampon üzerinde işaretçiler! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Dizi kopyalama: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 — bağımsız
Yapıları kopyalarken: eğer yapı bir işaretçi alanı veya dilim alanı içeriyorsa, yalnızca referanslar kopyalanır, değerler değil.
Dilimleri "kopyalamak" için hangi yöntemi kullanmalıyız ki, değişiklikleri orijinalini etkilemesin?
Potansiyel olarak hatalı cevap: Sadece b := a yapmak. Doğru:
copy kullanmalısınız, uygun uzunlukta yeni bir dilim oluşturmalı ve verileri kopyalamalısınız:newS := make([]int, len(a)) copy(newS, a)
Hikaye
Açıklama: Dinamik olarak sorgular oluşturulurken, kopya yapılmadan yapıdaki dilim alanlarının alanları değiştirildi. Tekrar eden sorgularda veriler çakıştı ve kullanıcılar için hatalı sonuçlar verildi.
Hikaye
Açıklama: Paralel veri işleme sırasında, bir atama yoluyla yapının kopyası oluşturuldu ve bir goroutine içinde dilimi genişletirken, diğer orijinal dilim kullanıldı. Veriler "üst üste bindi", tahmin edilemeyen hatalara neden oldu.
Hikaye
Açıklama: Bir yapı-buffer kullanıldı, eşzamanlı kopyalama atama yoluyla iç içe dilimleri dikkate almadı (sığ kopyalama), bir yerdeki değişiklikler diğer buffer'ı etkiledi — sonuç olarak verilerdeki değişikliğin kaynağını takip etmek zor hale geldi.