Срез смотрит на последовательность
Срез похож на последовательность элементов с удобной длиной, которая может меняться. Технически он описывает участок базового массива, поэтому два среза иногда могут видеть одни и те же элементы.
Литерал []string{"чай", "кофе"} создаёт срез сразу с данными. Выражение items[a:b] берёт элементы от индекса a включительно до b не включительно. Если начало опустить, оно будет нулём; если опустить конец, срез дойдёт до конца доступной длины.
len — текущее число элементов, а cap — сколько элементов помещается от начала среза в его базовом массиве. append возвращает новый срез; всегда присваивай результат обратно, поскольку при нехватке ёмкости Go может выделить другой базовый массив.
Пример
package main
import "fmt"
func printQueue(queue []string) {
for position, name := range queue {
fmt.Printf("%d. %s\n", position+1, name)
}
}
func main() {
queue := make([]string, 0, 4)
queue = append(queue, "Лена", "Игорь", "Марат")
printQueue(queue[:2])
queue = append(queue, "Оля", "Нина")
fmt.Printf("длина: %d, ёмкость: %d\n", len(queue), cap(queue))
printQueue(queue)
}
Функция принимает []string, поэтому ей подходит срез любой длины. После добавления двух имён выводятся все пять участников; ёмкость после роста может быть больше запрошенной и зависит от реализации Go, поэтому программу не следует проверять по конкретному числу cap.
Разделение с базовым массивом
Изменение элемента в срезе может изменить и другой срез, если оба ссылаются на один базовый массив. Добавление в конец также может использовать уже имеющуюся ёмкость. Если данным нужна независимость, скопируй их в новый срез с помощью copy или выдели новый массив.
Нельзя нарезать за пределами доступной длины базовой последовательности. Для пустого среза можно заранее зарезервировать место: make([]int, 0, 10) создаёт длину 0 и ёмкость не меньше 10.