tgoop.com/go_interview_lib/519
Create:
Last Update:
Last Update:
💬 Срезы в Go всегда аллоцируются в куче?
Срезы состоят из двух частей: заголовка среза (который представляет собой структуру с тремя полями) и базового массива, который может находиться либо на стеке, либо в куче.
1. Первый случай: и срез, и базовый массив находятся на стеке.
func doSomething() {
a := byte(1)
println("a's address:", &a)
s := make([]byte, 1)
println("slice's address:", &s)
println("underlying array's address:", s)
}
Вывод примера показывает, что и переменная
a
, и срез s
, и его базовый массив выделяются на стеке, их адреса близки. Go может оптимизировать это размещение, так как размер массива известен во время компиляции.2. Базовый массив начинается на стеке, затем перемещается в кучу.
func main() {
slice := make([]int, 0, 3)
println("slice:", slice, "- slice addr:", &slice)
slice = append(slice, 1, 2, 3)
println("slice full cap:", slice)
slice = append(slice, 4)
println("slice after exceed cap:", slice)
}
В этом случае адрес базового массива меняется, когда срез превышает свою емкость. Это означает, что массив теперь находится в куче.
3. Базовый массив сразу выделяется в куче.
Если емкость среза больше 64 КБ, базовый массив будет выделен в куче, как видно в следующем примере:
func main() {
sliceA := make([]int, 64 * 1024)
sliceB := make([]int, 64 * 1024 + 1)
println("sliceA:", sliceA)
println("sliceB:", sliceB)
}
В результате массив для
sliceA
находится на стеке, а для sliceB
— в куче.🤔 Как избежать выделения памяти в куче?
Лучший способ — заранее оценить необходимую емкость среза, используя
make()
с установленной емкостью. Это уменьшит вероятность дополнительных выделений памяти. Также можно использовать sync.Pool
для повторного использования массивов.BY Библиотека Go для собеса | вопросы с собеседований
Share with your friend now:
tgoop.com/go_interview_lib/519