Если емкость среза в Голанге может быть превышена, почему параметр емкости вообще стоит?
Я не знаю, чтоВы подразумеваете под этим, но емкость не может быть превышена.Срезы могут быть проиндексированы вплоть до его длины (исключая), которая не может превышать емкость, и они могут быть повторно разрезаны до ее емкости (включительно).
Spec: Индексные выражения:
Первичное выражение вида a[x]
Если a
не является картой: ... индекс x
равен в диапазоне если 0 <= x < len(a)
, в противном случае выходит за пределы диапазона
и Spec: выражения среза:
... Первичное выражение: a[low : high]
Для массивов или строк индексы находятся в диапазоне в диапазоне , если 0 <= low <= high <= len(a)
, в противном случае они находятся вне диапазона .Для слайсов верхняя граница индекса - это емкость слайса cap(a)
, а не длина.
А также:
... основное выражение: a[low : high : max]
Индексы в диапазоне , если 0 <= low <= high <= max <= cap(a)
, в противном случае они вне диапазона .
Вы можете предоставить емкость длявстроенный make()
думает о будущем росте, поэтому потребуется меньше ассигнований, если вам нужно будет добавить элементы к нему или вам нужно будет заменить его.Встроенный append()
просто повторяет фрагмент, к которому вы добавляете, если у него достаточно места для дополнительных элементов, но он должен выделить новый резервный массив (и скопировать в него существующее содержимое), если у него неткомната для новых элементов.append()
вернет новый фрагмент, который может указывать или не указывать на исходный массив поддержки.
Давайте рассмотрим пример.Давайте создадим срез длиной 0 и емкостью и добавим к нему 10 элементов.И чтобы увидеть, когда происходит новое перераспределение, мы также печатаем адрес его первого элемента (0-й элемент):
fmt.Println("With 0 capacity")
s := make([]int, 0)
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Println(i, &s[0])
}
Это выводит:
With 0 capacity
0 0x416030
1 0x416030
2 0x416040
3 0x416040
4 0x452000
5 0x452000
6 0x452000
7 0x452000
8 0x434080
9 0x434080
Как вы можете видеть,новый резервный массив выделяется, когда мы добавили третий (i=2
), пятый (i=4
) и девятый элементы (i=8
), а также когда мы добавили первый элемент (поскольку исходный резервный массив не мог содержать какой-либоэлементы).
Теперь давайте повторим приведенный выше пример, когда мы создадим начальный срез с длиной length = 0, но с емкостью = 10:
fmt.Println("With 10 capacity")
s = make([]int, 0, 10)
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Println(i, &s[0])
}
Теперь вывод будет:
With 10 capacity
0 0x44c030
1 0x44c030
2 0x44c030
3 0x44c030
4 0x44c030
5 0x44c030
6 0x44c030
7 0x44c030
8 0x44c030
9 0x44c030
Как вы можете видеть, адрес первого элемента никогда не менялся, что означает, что в фоновом режиме не было новых выделений резервного массива.
Попробуйте пример на Go Playground .