Механизм append
В разделе Capacity мы написали функцию Extend, которая расширяет срез на один элемент. Однако наше решение не совсем верное, потому что при превышении емкости слайса программа уйдет в панику (panic). В нашем примере в функции Insert та же проблема. Теперь у нас есть все необходимое, чтобы это исправить, так что давай напишем надежную реализацию расширения целочисленных срезов.
В этом случае особенно важно вернуть слайс, так как при перераспределении результирующий слайс описывает совершенно другой массив. Вот небольшой фрагмент, демонстрирующий, что происходит, когда срез заполняется.
Самое время протестировать код!
Обрати внимание на перераспределение, когда исходный массив размером 5 заполнен. Емкость и адрес нулевого элемента изменяются при выделении нового массива.
Используя надежную функцию Extend в качестве руководства, мы можем написать еще более удобную функцию, которая позволит нам расширить срез на несколько элементов. Для этого мы используем способность Go превращать список аргументов функции в срез при вызове функции. То есть мы используем вариационную функцию Go.
Давай вызовем функцию Append. Для первой версии мы можем просто вызывать Extend несколько раз, чтобы механизм вариативной функции был ясен. Сигнатура функции Append:
Эта сигнатура функции Append принимает первый аргумент, срез, за которым следует ноль или более аргументов с типом int.
Самое время протестировать код!
Обрати внимание на цикл for, range, перебирающий элементы items, обладающий типом []int. Также обрати внимание на использование пустого идентификатора _, c помощью этого blank identifier мы опускаем индекс в цикле, который в данном случае нам не нужен.
Другой новый метод в этом примере заключается в том, что мы инициализируем срез, записывая составной литерал. Он который состоит из типа среза, за которым следуют его элементы в фигурных скобках.
Функция Append интересна по другой причине. Мы можем не только добавлять элементы, но и добавлять целый второй слайс, «распаковывая» слайс на аргументы, используя нотацию ... в месте вызова.
Самое время протестировать код!
Конечно, мы можем повысить эффективность функции Append, выделяя память не более одного раза. Перепишем Append, опираясь на функцию Extend.