@Byrger
Разработчик ПО для платежных систем

Что такое емкость среза?

Подскажите что такое емкость среза в Go?

Допустим
slice := make([]int, 10, 15)
	fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
	fmt.Println(slice)

Выводит
len: 10, cap: 15
[0 0 0 0 0 0 0 0 0 0]


И
slice := make([]int, 10, 30)
	fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
	fmt.Println(slice)


Выводит тот-же массив [0 0 0 0 0 0 0 0 0 0]

Я думал что это максимальная возможность записи в массив но попробовав записать slice[11]=0
Получил паник =(

Прочитал статьи про срезы но так и не понял что такое емкость и для чего она нужна
  • Вопрос задан
  • 2763 просмотра
Решения вопроса 1
xotkot
@xotkot
хорошо есть и хорошо весьма
если по простому и коротко, то для среза:
ёмкость(cap) - это выделенная память под элементы, при превышении размер автоматически увеличивается в два раза.
длина(len) - это инициализированная память элементов, для превышения(добавления) нужно вручную использовать append.
По умолчанию cap = len
Всегда будет cap >= len
Грубо говоря, cap выделяет память, а len инициализирует её всю или только часть .

slice := make([]int, 2, 2) // эвивалентно slice := []int{0,0}
fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
fmt.Println(slice)

slice = append(slice, 3)

fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
fmt.Println(slice)

выведет:
len: 2, cap: 2
[0 0]

len: 3, cap: 4
[0 0 3]


п.с.
если конкретно по вашему примеру то в первом и во втором случае у вас инициализировано только 10 элементов которые команда fmt.Println(slice) и выводит.
А паника при slice[11]=0 будет из за того что этот 11 элемент не инициализирован, хоть память под него и выделена, здесь необходимо использовать append.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Neuroware
@Neuroware
Программист в свободное от работы время
Срез это структура данных описывающая множественное разделение массива и хранящееся отдельно от переменной. Срез это не массив. Срез описывает часть массива.

Если мы возьмем массив buffer из предыдущего раздела, то мы можем создать срез, который будет описывать элементы от 100 до 150 (если быть точным, то от 100 до 149 включительно) путем нарезания массива:
var slice []byte = buffer[100:150]

В этом куске кода, чтобы быть точными, мы использовали полное объявление переменной. Переменная slice имеет тип []byte, читается как «срез байтов» (slice of bytes) и создана из массива buffer, путем нарезания начиная с элемента 100 (включительно) до 150 (исключительно).

То есть вкратце если я правильно понял вопрос, нужно сначала создать массив, обычный, потом можно внутри него выделить срез, и только после этого можно работать со срезом.
Ответ написан
Комментировать
evnuh
@evnuh
Поиск Гугл помог мне, впусти и ты его в свой дом
https://blog.golang.org/slices прочитайте и всё станет понятно.

Если кратко, то ёмкость слайса - длина массива, который хранит элементы слайса. Попросту говоря это Байты оперативки, выделенные под хранение ваших данных. Оно всегда больше или равно длины слайса.
Сам слайс это указатель на какой-либо из элементов в этом масиве (не оьязательно первый) + длина. Это искуственное ограничение, фактически это отрезок массива, в котором что-то записано. При добавлении в слайс нового элемента слайс увеличит свою длину на 1, пооказывая что кол-во данных в массиве увеличилось на 1, а емкость самого массива не изменится, если её хватало для хранения нового элемента. Если же весь массив был заолнен, то слайс просто выделит новый массив в памяти большей ёмкости (обычно в два раза большей предыдущей ёмкости) и перенесёт все данные туда вместе с новым добавленным элементом. При этом, очевидно, сам слайс не изменит своей длины, т.к. Кол-во данных не изменилось, а только поменяет указатель на начальный элемент, т.к. Массив с данными выделен новый по новому адресу в памяти.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы