MyTetra Share
Делитесь знаниями!
Срезы (слайсы, slice) в Golang
Время создания: 12.11.2020 18:29
Автор: br0ke
Текстовые метки: go, golang, slice, slices, array, arrays, dynamic, len, cap, length, capacity
Раздел: Информационные технологии - Golang
Запись: and-semakin/mytetra_data/master/base/1605187775jzyzxrq53x/text.html на raw.githubusercontent.com

Срез -- это гомогенная (данные должны быть одного типа) последовательность переменной длинны. В других языках подобные структуры данных называют динамическими массивами или списками.


Массивы и срезы в Go тесно связаны. Срез -- это структура данных, которая строится поверх массива и предоставляет доступ к элементами базового массива.


Срез состоит из следующих трёх компонентов:

  1. ссылка на первый доступный через срез элемент базового массива;
  2. длина (length) -- количество элементов в срезе;
  3. емкость (capacity) -- количество элементов между началом среза и концом базового массива; означает количество элементов, которые можно добавить в срез, без реаллокаций.


Длина и ёмкость среза могут быть определены при помощи встроенных функций len() и cap() соответственно.


Создание среза


Объявление


Объявить срез можно примерно так же, как и массив, за исключением того, что нет необходимости указывать длину (т.к. она изменяема):


var a []int // срез длины 0, потому что в этом случае базовый массив даже не создаётся

var b []int = []int{1, 2, 3}

c := []int{1, 2, 3}

d := []int{1: 12} // компилятор инициализирует массив необходимой длины нулевыми значениями


fmt.Println(a) // []

fmt.Println(b) // [1 2 3]

fmt.Println(c) // [1 2 3]

fmt.Println(d) // [0 12]


Создание среза через make


Более идеоматичным и гибким способом создать пустой срез является использование встроенной функции make():


make([]T, length, capacity)


Например:


a := make([]int, 10, 20)

// len(a) == 10

// cap(a) == 20


Имеет смысл сразу же создавать срезы с запасом по ёмкости, если ожидается активно их расширять.


Если емкость среза равна его длине, то третий аргумент можно опустить:


a := make([]int, 10)

// len(a) == 10

// cap(a) == 10


Извлечение среза из массива


Также срез можно получить при помощи операции извлечения среза из массива или другого среза. При операции извлечения среза указывается полуоткрытый диапазон индексов массива (нижняя граница включительно, верхняя граница невключительно). Если опустить одну из границ, то она по умолчанию будет равна либо 0, либо длине массива соответственно. Например:


initialUsers := [8]string{"Bob", "Alice", "Kate", "Sam", "Tom", "Paul", "Mike", "Robert"} // базовый массив


users1 := initialUsers[2:6] // с 3-го по 6-й

users2 := initialUsers[:4] // с 1-го по 4-й

users3 := initialUsers[3:] // с 4-го до конца


fmt.Println(users1) // [Kate Sam Tom Paul]

fmt.Println(users2) // [Bob Alice Kate Sam]

fmt.Println(users3) // [Sam Tom Paul Mike Robert]


В этом примере базовый массив остаётся одним и тем же, но на его основе создаётся три разных среза, которые предоставляют доступ к части его данных.


Если изменять данные через срезы, то будет изменяться и базовый массив. Соответственно, изменения смогут быть видны и через другие срезы, которые основываются на том же базовом массиве.


Функции для работы со срезами


append -- добавление элементов в срез. Функция либо дописывает значения в существующий массив, если ёмкость позволяет, либо реаллоцирует (создаёт новый массив большего размера и переносит данные в него), и добавляет данные в него. Функция возвращает новый объект обновлённого среза, который обязательно нужно сохранить.


slice = append(slice, elem1, elem2)

slice = append(slice, anotherSlice...)


copy -- скопировать данные из одного среза в другой. Возвращает количество скопированных элементов -- минимум из len(src) и len(dst).


a := []int{1, 2, 3}

b := make([]int, 3, 3)

n := copy(b, a)


fmt.Printf("a = %v\n", a) // a = [1 2 3]

fmt.Printf("b = %v\n", b) // b = [1 2 3]

fmt.Printf("Скопировано %d элемента\n", n) // Скопировано 3 элемента


Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования