Я новичок в 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, то первый поместил бы объект в кучу, а второй — в стек. Первый вернет указатель на кучу, второй вернет указатель на стек, который испарится к моменту возврата функции, что будет Плохой вещью.
Если бы я написал его на Python (или многих других современных языках, кроме C#), пример 2 был бы невозможен.
Я понимаю, что мусор Go собирает оба значения, так что обе приведенные выше формы подходят.
Процитирую:
Обратите внимание, что, в отличие от C, совершенно нормально возвращать адрес локальная переменная; хранилище, связанное с переменной, сохраняется после возврата функции. Фактически, взяв адрес составного литерал выделяет новый экземпляр каждый раз, когда он оценивается, поэтому мы можно объединить эти две последние строки.
Но возникает пара вопросов.
1 — В примере 1 структура объявлена в куче. А пример 2? Объявлено ли это в стеке так же, как в C, или оно также находится в куче?
2 - Если пример 2 объявлен в стеке, как он остается доступным после возврата функции?
3. Если пример 2 фактически объявлен в куче, как получается, что структуры передаются по значению, а не по ссылке? Какой смысл в указателях в этом случае?