Appearance
Slice
Структура слайса:
- указатель на элемент базового массив. Не обязательно на 0ой, но это будет 0ой элемент этого слайса
- длина слайса. Сколько есть элементов в текущем слайсе
- емкость слайса. Сколько элементов поместится в слайс без необходимости переопределения базового массива
При передаче слайса по значению в функцию передается указатель на элемент базового массива, поэтому передавать по ссылке для экономии памяти особого смысла нет.
go
var arr []int
arr == nil // true
len(arr) == 0 // true
arr := []int{}
arr == nil // false
len(arr) == 0 // true
Видимо при var arr []int
базовый массив не инициализируется, поэтому nil. А во 2ом примере базовый массив инициализируется
Функция принимает на вход слайс и переменное количество элементов для добавления в слайс. Append расширяет слайс за пределы его len, возвращая при этом новый слайс.
append. Если количество элементов, которые мы добавляем в слайс, не будет превышать cap, вернется новый слайс, который ссылается на тот же базовый массив, что и предыдущий слайс. Если количество добавляемых элементов превысит cap, то вернется новый слайс, базовым для которого будет новый массив.
На данный момент при нехватке памяти в слайсе создается новый базовый массив примерно в 2 раза больше прежнего, если число элементов небольшое. Если элементов много, размер увеличивается более плавно. В результате в слайсе получается указатель на другую область памяти
Если нужна защитить слайс от изменения, можно воспользоваться встроенной функцией copy()
go
slice := append([]byte("hello "), "world"...) // так можно
go
a := [5]int{1, 2, 3, 4, 5}
t := a[1:2:len(a)] // это способ задать capacity слайса. cap = последний элмент - первый. т.е. 5 - 1 = 4.
fmt.Println(t[0]) // 2
fmt.Println(cap(t)) // 4