Go derleyicisi escape analysis (işaretçi kaçış analizi) mekanizmasını kullanır: varsayılan olarak tüm değerler yığında saklanır, ancak bir değişken "alana" (görünürlük içinde) dönmediğinde (örneğin, yerel bir değişkenin işaretçisi döndüğünde) otomatik olarak yığın dışında (heap) yerleştirilir.
Bu, performans açısından önemlidir:
Derleyici, bir nesnenin yığında yerleştirilebilir mi olduğunu belirlemeye çalışır, ancak eğer fonksiyon sınırlarını “aşarsa” – yığın dışına yerleştirir.
Kaçış örneği:
func NewPoint() *int { a := 42 return &a // heap'e kaçış! }
Kaçış olmayan örnek:
func Sum(a, b int) int { c := a + b return c // yığında }
Derleyici tarafından tanı koymak için go build -gcflags='-m' kullanın, detayları görmek için:
go build -gcflags='-m' main.go
"Eğer fonksiyondan yalnızca değeri dönersek - işaretçi değil - nesne heap'e gider mi?"
Sıklıkla, döndürülen her değerin "heap'e geçtiği" düşünülür. Aslında, eğer bir değer (işaretçi değil) döndürülüyorsa, değişken yığında kalabilir.
Örnek:
func F() int { x := 10 return x // yığın tahsisi, heap'e geçmez }
Hikaye
Yerel değişkenlere işaretçi dönen bir fabrika fonksiyonu ile yapısal nesnelerin topluca oluşturulması sırasında bellek kullanımı ve GC yükü aniden arttı. Görüldü ki: tüm nesneler, işaretçiyi döndürdüğünden heap'e kaçıyordu, oysa değeri döndürerek bu durumdan kaçınmak mümkün olabilirdi.
Hikaye
Microservice'de, goroutinler arasında işaretçi ile değişken geçişi ve farklı fonksiyonlardan döndürmeler sonucunda, yığından birçok nesne heap'e “sızıyordu”, bu da işlemi yavaşlatıyor ve sık sık GC duraklamalarına neden oluyordu.
Hikaye
Bir geliştirici, bir işlev içinde statik bir diziyi dilim (slice) ile sardı, dilim üzerinde işaretçi döndürdü ve yük testi sırasında bellek sızıntıları yaşamaya başladı. Tanımlama, değişkenin işlev sınırlarını “aşmadığını” gösterdi, ancak Go yanılgılı olarak dolaylı kullanım nedeniyle onu heap'e yerleştirmeye karar verdi.