Как известно, в Go фаза escape analysis решает, кто и куда будет аллоцирован - в кучу или на стек. Базовое правило простое: живешь в пределах функции - на стек, живешь дольше - на кучу.
И Go, как язык самостоятельный, иногда может решить аллоцировать на кучу то, что мы ожидали на стеке. Плюс в том, что Go сам умеет объяснять, почему он это сделал.
Достаточно запустить build с флагом -m:
go build -gcflags='-m' ./...
И компилятор выдаст подобный листинг:
./main.go:23:13: &user escapes to heap
./main.go:45:22: moved to heap: buf
Что это значит:
-
escapes to heap - компилятор понял, что значение будет жить дольше функции и положил его в кучу - часто это происходит из-за того, что ты вернул указатель на локальную переменную или замкнул переменную в анонимную функцию:
func outer() func(int) int {
local := 10
return func(x int) int {
return x * local // local уходит в кучу
}
}
Иногда достаточно переписать сигнатуру или убрать лишний & - и аллокации исчезают, и это хороший способ выжать из Go больше перфоманса.
dev notes | golang digest