Jestem nowy w Go i doświadczam nieco zbieżnego dysonansu między programowaniem opartym na stosie w stylu C, w którym zmienne automatyczne żyją na stosie i przydzieloną pamięć na stercie i programowaniem opartym na stosie w stylu Pythona, gdzie jedyną rzeczą, która żyje na stosie, są odniesienia / wskaźniki do obiektów na stercie.
O ile wiem, dwie następujące funkcje dają ten sam wynik:
func myFunction() (*MyStructType, error) {
var chunk *MyStructType = new(HeaderChunk)
...
return chunk, nil
}
func myFunction() (*MyStructType, error) {
var chunk MyStructType
...
return &chunk, nil
}
tj. przydziel nową strukturę i zwróć ją.
Gdybym napisał to w C, pierwszy umieściłby obiekt na stercie, a drugi na stosie. Pierwsza zwróciłaby wskaźnik do stosu, druga zwróciłaby wskaźnik do stosu, który wyparowałby do czasu zwrócenia funkcji, co byłoby złą rzeczą.
Gdybym napisał to w Pythonie (lub wielu innych współczesnych językach oprócz C #), przykład 2 nie byłby możliwy.
Rozumiem, że śmieci Go gromadzą obie wartości, więc obie powyższe formy są w porządku.
Cytować:
Zauważ, że w przeciwieństwie do C, zwrócenie adresu zmiennej lokalnej jest całkowicie OK; pamięć związana ze zmienną przetrwa po powrocie funkcji. W rzeczywistości pobranie adresu literału złożonego przydziela nowe wystąpienie za każdym razem, gdy jest ono oceniane, więc możemy połączyć te dwie ostatnie linie.
Ale rodzi kilka pytań.
1 - W przykładzie 1 struktura jest zadeklarowana na stercie. A co z przykładem 2? Czy jest to zadeklarowane na stosie w taki sam sposób, w jaki byłoby to w C, czy też trafia na stos?
2 - Jeśli przykład 2 jest zadeklarowany na stosie, w jaki sposób pozostaje on dostępny po powrocie funkcji?
3 - Jeśli przykład 2 jest faktycznie zadeklarowany na stercie, w jaki sposób struktury są przekazywane przez wartość, a nie przez odwołanie? Jaki jest sens wskazówek w tym przypadku?