Как работает append в Go
Вопрос
Расскажите, что происходит при s = append(s, x), и почему результат append обязательно присваивают.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Если `len < cap`, элемент пишется в существующий массив, len растёт на 1
Если места нет, выделяется новый массив большей ёмкости, данные копируются
Рост: удвоение для маленьких, плавнее после ~256 элементов, плюс округление под классы аллокатора
append возвращает новый заголовок, старый может указывать на другой массив и иметь старый len
Подслайсы одного массива могут затирать данные друг друга через append
Предвыделение `make([]T, 0, n)` убирает лишние аллокации
Что могут спросить следом
- Почему точное значение cap после append нельзя закладывать в тесты?
- Как удалить элемент из середины слайса без утечки указателей?
- Что сделает append, если слайс nil?
Разбор
append смотрит на ёмкость. Если len < cap, он кладёт элемент в следующий свободный слот того же массива и возвращает заголовок с len на единицу больше. Если места нет, рантайм (growslice) выделяет новый массив: для маленьких слайсов примерно вдвое больше, после порога в 256 элементов рост плавнее, около 1.25x плюс константа, и итог округляется до класса размера аллокатора. Старые элементы копируются, и с этого момента новый слайс живёт отдельно от старого. Поэтому результат всегда присваивают: заголовок может быть другим и по указателю, и по len. Отсюда же баги: два подслайса одного массива при append перезаписывают друг друга, пока есть ёмкость. Лечится полным срезом a[i:j:j] или копированием. Если размер известен, делаю make([]T, 0, n), чтобы не было промежуточных аллокаций и копий. append к nil-слайсу работает как к пустому.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Слайсы и мапы изнутри»
- Разбить слайс на части по k на Go
- Удаление дубликатов с сохранением порядка на Go
- Группировка анаграмм на Go
- Циклический сдвиг слайса на Go
- Число подмассивов с суммой k на Go
- Топ-k частых слов на Go
- Что выведет Go: append при полной ёмкости
- Что выведет Go: два append в один подслайс