Срез не хранит никаких данных, он просто описывает часть базового массива.
Когда вы изменяете элемент среза, вы модифицируете соответствующий элемент его базового массива, и другие срезы, которые совместно используют тот же базовый массив, увидят это изменение.
Срез может расти и уменьшаться в пределах основного массива.
Срезы индексируются обычным способом: s[i] обращается к i-му элементу, начиная с нуля.
Создание
var s []int // nil срез
s1 := []string{"foo", "bar"}
s2 := make([]int, 2) // то же что и []int{0, 0}
s3 := make([]int, 2, 4) // то же что и new([4]int)[:2]
fmt.Println(len(s3), cap(s3)) // 2 4
Нулевым значением по умолчанию для среза является nil. Функции len, cap и append все рассматривают nil как пустой срез с нулевой емкостью.
Вы создаете срез с помощью литерала среза или вызова функции make, которая принимает длину и необязательную емкость в качестве аргументов.
Встроенные функции len и cap определяют длину и емкость.
Нарезка
a := [...]int{0, 1, 2, 3} // массив
s := a[1:3] // s == []int{1, 2} cap(s) == 3
s = a[:2] // s == []int{0, 1} cap(s) == 4
s = a[2:] // s == []int{2, 3} cap(s) == 2
s = a[:] // s == []int{0, 1, 2, 3} cap(s) == 4
Вы также можете создать срез, разрезая существующий массив или срез.
Срез формируется путем указания нижней границы и верхней границы: a[low:high]. Эта конструкция выбирает полуоткрытый диапазон, который включает первый элемент, но исключает последний.
Вы можете опустить верхние или нижние границы, чтобы использовать их значения по умолчанию. По умолчанию ноль для нижней границы и длина среза для верхней границы.
s := []int{0, 1, 2, 3, 4} // срез
s = s[1:4] // s == []int{1, 2, 3}
s = s[1:2] // s == []int{2} (индексирование относительно среза)
s = s[:3] // s == []int{2, 3, 4} (расширение длины)
Когда вы нарезаете срез, индексы относятся к самому срезу, а не к подлежащему массиву.
Верхняя граница связана не с длиной среза, а с его емкостью, что означает, что вы можете увеличить длину среза.
Попытка выйти за пределы возможностей вызывает панику.
Итерация
s := []string{"Foo", "Bar"}
for i, v := range s {
fmt.Println(i, v)
}
Вывод:
0 Foo
1 Bar
Выражение диапазона s вычисляется один раз перед началом цикла.
Значения итерации присваиваются соответствующим переменным итерации, i и v, как в операторе присваивания.
Вторая итерационная переменная является необязательной.
Если срез равен nil, количество итераций равно 0.
Append и copy
Функция append добавляет элементы к срезу. Он будет автоматически выделять больший резервный массив при превышении емкости.
Функция copy копирует элементы в целевой срез dst из исходного среза src. Количество копируемых элементов - это минимум len(dst) и len(src).
Стеки и очереди
Идиоматический способ реализации стека или очереди в Go - это непосредственное использование среза.
Читайте также:
- Массивы, срезы и строки: механика работы append в Golang
- Срезы в Golang: внутреннее устройство и использование
- Эффективный Go: срезы (slices)
Комментариев нет:
Отправить комментарий