Middle+
Kur yra kintamoji, kai ji išryškinama gorutinoje?
sobes.tech AI
Atsakymas iš AI
Kintamasis gali būti išskirtas tiek steko, tiek krūvos. Tai nustatoma naudojant Go kompiliatoriaus escape analysis (išsilaisvinimo analizės) mechanizmą.
Pagrindiniai išsilaisvinimo analizės principai:
- Jei kompiliatorius gali įrodyti, kad kintamasis gyvena tik vieno funkcijos iškvietimo viduje arba tik steko ribose vienos gorutinos (tai yra, nėra nuorodų į jį iš išorės), jis išskiriamas į tos gorutinos steką. Tai yra greičiau, nes stekas valdomas automatiškai ir nereikalauja šiukšlių surinkimo.
- Jei kompiliatorius negali įrodyti, kad kintamasis yra ribojamas steko, arba jei jam yra nuorodų iš išorės (pavyzdžiui, perduodamas per nuorodą į kitą funkciją, įrašomas į globalią kintamąjį, grąžinamas iš funkcijos per nuorodą), jis išskiriamas į krūvą. Krūva reikalauja šiukšlių surinkimo, kas gali sulėtinti vykdymą.
Pavyzdys, kaip išskiriama steke:
// Kintamasis 'x' išskiriamas į gorutinos steką, nes naudojamas tik funkcijos viduje.
func exampleStack() int {
x := 10
return x
}
Pavyzdys, kaip išskiriama krūvoje:
// Kintamasis 'p' (nuoroda į int) ir į kurį jis nuorodo, gali būti išskirti į krūvą.
// Tai vyksta todėl, kad nuoroda grąžinama iš funkcijos ir gali būti naudojama iš išorės.
func exampleHeap() *int {
x := 20 // Reikšmė 20 gali būti išskirta į krūvą
return &x // Grąžiname kintamojo x adresą
}
Išsilaisvinimo analizė vyksta kompiliacijos metu. Ją galima patikrinti naudojant -gcflags "-m" žymę:
go build -gcflags "-m" your_package_name
Kompiliatoriaus išvestis parodys, kurie kintamieji "escape to heap".
Taigi, kintamojo vieta (stekas vs krūva) nėra nustatoma pagal tai, ar kintamasis išskiriamas į gorutinos atmintį, o pagal tai, kaip Go kompiliatorius analizuoja jo gyvavimo ciklą ir matymo sritis.