Где в Go аллоцируется память для слайса: в стеке или в куче?

Ответ

Слайс в Go — это структура-заголовок (slice header), которая содержит указатель на базовый массив, длину (len) и ёмкость (cap). Вопрос об аллокации слайса на самом деле сводится к вопросу, где будет размещен его базовый массив.

По умолчанию, базовый массив для слайса аллоцируется в куче (heap).

Однако, компилятор Go проводит анализ побега (escape analysis). Если компилятор определяет, что массив не будет использоваться за пределами функции, в которой он создан (т.е. не "сбегает"), и его размер невелик и известен на этапе компиляции, он может быть аллоцирован на стеке (stack) для повышения производительности.

Ключевые факторы:

  • Escape Analysis: Основной механизм, решающий, куда поместить данные.
  • Размер данных: Небольшие аллокации с большей вероятностью останутся на стеке.
  • Время жизни: Если данные должны пережить вызов функции (например, возвращаются из нее), они будут перемещены в кучу.

Пример:

package main

//go:noinline
func createStackSlice() {
    // Этот слайс, скорее всего, будет аллоцирован на стеке.
    // Размер известен, и слайс не покидает пределы функции.
    stackSlice := make([]int, 10)
    _ = stackSlice
}

//go:noinline
func createHeapSlice() []int {
    // Этот слайс будет аллоцирован в куче, так как он
    // "сбегает" из функции (возвращается наружу).
    heapSlice := make([]int, 10)
    return heapSlice
}

func main() {
    createStackSlice()
    _ = createHeapSlice()
}