Я новичок в Go, и я испытываю немного противоречивого диссонанса между программированием на основе стека C-стиля, где автоматические переменные живут в стеке, а выделенная память живет в куче и в стиле Python, программирование, где единственное, что живет в стеке, - это ссылки/указатели на объекты в куче.
Насколько я могу судить, две следующие функции дают один и тот же результат:
func myFunction() (*MyStructType, error) {
var chunk *MyStructType = new(HeaderChunk)
...
return chunk, nil
}
func myFunction() (*MyStructType, error) {
var chunk MyStructType
...
return &chunk, nil
}
то есть. выделите новую структуру и верните ее.
Если бы я написал это на C, первый бы поставил объект в кучу, а второй поместил бы его в стек. Первый вернет указатель на кучу, второй вернет указатель на стек, который бы испарился к тому времени, когда функция вернулась, что было бы Bad Thing.
Если бы я написал его на Python (или на многих других современных языках, кроме С#), пример 2 не был бы возможен.
Получаю, что Go мусор собирает оба значения, поэтому обе эти формы в порядке.
Цитата:
Обратите внимание, что, в отличие от C, вполне нормально возвращать адрес локальная переменная; сохраняется память, связанная с переменной после возвращения функции. Фактически, принимая адрес составного literal выделяет новый экземпляр каждый раз, когда он оценивается, поэтому мы могут объединить эти последние две строки.
Но это вызывает несколько вопросов.
1 - В примере 1 структура объявляется в куче. Как насчет примера 2? Является ли это объявленным в стеке таким же образом, что это будет в C или оно тоже будет в куче?
2 - Если в стеке объявлен пример 2, как он останется доступным после возвращения функции?
3 - Если пример 2 фактически объявлен в куче, как это происходит, то structs передаются по значению, а не по ссылке? Какая точка указателей в этом случае?