Я новичок в 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 действительно объявлен в куче, как получается, что структуры передаются по значению, а не по ссылке? Какой смысл указателей в этом случае?
В обоих случаях текущие реализации Go выделяют память для
struct
типаMyStructType
в куче и возвращают ее адрес. Функции эквивалентны; источник asm компилятора такой же.Все функции и возвращаемые параметры передаются по значению. Возвращаемое значение параметра с типом
*MyStructType
является адресом.источник
Согласно FAQ Го :
источник
Источник: http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html#stack_heap_vars
источник
Function1 и Function2 могут быть встроенными функциями. И возвращаемая переменная не уйдет. Нет необходимости размещать переменную в куче.
Мой пример кода:
По выводу cmd:
вывод:
Если компилятор достаточно умен, F1 () F2 () F3 () может не вызываться. Потому что это не значит.
Не важно, будет ли переменная размещена в куче или стеке, просто используйте ее. Защитите его мьютексом или каналом, если это необходимо.
источник