Go'da varsayılan olarak fonksiyon argümanları değer ile aktarılır: değişkenin değeri kopyalanır. Ancak bazı türler (örneğin dilimler, haritalar, kanallar) iç yapılar (işaretçiler) üzerinde 'sarmalayıcılar' olarak işlev görür. Dilimin değer ile aktarılması, yalnızca dilim başlığını kopyalar, verileri değil; her iki değişken de aynı diziye işaret eder. Yapılarda ise tüm yapı kopyalanır.
Kopyalamayı önlemek ve orijinal yapı ile çalışmak gerekiyorsa, işaretçi ile aktarma kullanılır (*Struct).
type User struct { Name string Age int } func updateUser(u User) { u.Age = 30 // sadece kopyayı değiştirir } func updateUserPtr(u *User) { u.Age = 30 // orijinali değiştirir } func main() { u := User{"Ivan", 25} updateUser(u) fmt.Println(u.Age) // 25 updateUserPtr(&u) fmt.Println(u.Age) // 30 }
Fonksiyona geçirilen bir dilimdeki değişiklikler her zaman fonksiyonun dışından görülebilir mi?
Hayır!
slice[i] = ...), bu dışarıda görünür.slice = append(slice, ...)), ve sonuç fonksiyondan geri döndürülmezse — yeni elemanlar yerel kopyada kalır ve kaybedilir.func addElem(s []int) { s = append(s, 100) } func main() { arr := []int{1,2,3} addElem(arr) fmt.Println(arr) // [1 2 3] — 100 eklenmedi }
Hikaye
Bir projede, büyük bir alanı olan veri yapıları (200+ byte) kanallar aracılığıyla goroutine'ler arasında değer olarak aktarılıyordu, bu da kopyalama yoluyla büyük maliyetler ve performans kaybı yaratıyordu. İşaretçi ile aktarım geçişi sonrası gecikme bir öncekinden çok azaldı.
Hikaye
Bir denetim günlüğü servisinde, geliştirici bir haritayı (map) fonksiyonlar arasında açık bir kopyalama olmadan aktarıyordu. Bir fonksiyon tarafından yapılan değişiklikler, programın başka bir kısmındaki verileri beklenmedik şekilde değiştiriyor ve günlüğü karıştırıyordu.
Hikaye
Fonksiyon içinde dilimin dinamik olarak artırılması fonksiyonunda, yeni dilimi geri döndürmeyi unuttular. Sonuç olarak, değişiklikler çağıran kodda yansıtılmadı ve bazı işlemlerin kaybına yol açtı. Fonksiyondan yeni bir dilim döndürmeyi kararlaştırdılar.