Sobes.tech
Middle+

Gdzie znajduje się zmienna, gdy jest wyróżniona w goroutine?

sobes.tech AI

Odpowiedź od AI

Zmienna może być alokowana zarówno na stosie goroutine, jak i na stercie. Jest to określane przez mechanizm escape analysis (analiza ucieczek) kompilatora Go.

Podstawowe zasady escape analysis:

  • Jeśli kompilator może udowodnić, że zmienna żyje tylko w ramach jednego wywołania funkcji lub tylko w zakresie stosu jednej goroutine (tzn. nie odwołuje się do niej z zewnątrz), jest alokowana na stosie tej goroutine. Jest to szybsze, ponieważ stos jest zarządzany automatycznie i nie wymaga zbierania śmieci.
  • Jeśli kompilator nie może udowodnić, że zmienna jest ograniczona do stosu, lub jeśli istnieją odwołania do niej z zewnątrz (np. przekazywana przez wskaźnik do innej funkcji, zapisywana w zmiennej globalnej, zwracana z funkcji przez wskaźnik), jest alokowana na stercie. Sterta wymaga zbierania śmieci, co może spowolnić wykonanie.

Przykład alokacji na stosie:

// Zmienna 'x' jest alokowana na stosie goroutine, ponieważ jest używana tylko wewnątrz funkcji.
func exampleStack() int {
	x := 10
	return x
}

Przykład alokacji na stercie:

// Zmienna 'p' (wskaźnik na int) i int, na który wskazuje, mogą być alokowane na stercie.
// Dzieje się tak, ponieważ wskaźnik jest zwracany z funkcji i może być używany z zewnątrz.
func exampleHeap() *int {
	x := 20 // Wartość 20 może być alokowana na stercie
	return &x // Zwracamy adres zmiennej x
}

Escape analysis odbywa się podczas kompilacji. Można to sprawdzić, używając flagi -gcflags "-m":

go build -gcflags "-m" your_package_name

Wyjście kompilatora pokaże, które zmienne "escape to heap".

W związku z tym, lokalizacja zmiennej (stos vs sterta) nie jest determinowana przez to, czy zmienna jest alokowana w goroutine, lecz przez to, jak kompilator Go analizuje jej cykl życia i zakres.