Поиск…
Вступление
Срез - это структура данных, которая инкапсулирует массив так, что программист может добавить столько элементов, сколько необходимо, не беспокоясь об управлении памятью. Срезы могут быть разрезаны на субрезки очень эффективно, так как результирующие срезы указывают на один и тот же внутренний массив. Похоже, программисты часто используют это, чтобы избежать копирования массивов, что обычно делается на многих других языках программирования.
Синтаксис
- slice: = make ([] type, len, cap) // создаем новый срез
- slice = append (slice, item) // добавление элемента в срез
- slice = append (slice, items ...) // добавляет срез элементов в срез
- len: = len (slice) // получить длину фрагмента
- cap: = cap (slice) // получить емкость среза
- elNum: = copy (dst, slice) // копирует содержимое среза на другой фрагмент
Добавление к срезу
slice = append(slice, "hello", "world")
Добавление двух срезов вместе
slice1 := []string{"!"}
slice2 := []string{"Hello", "world"}
slice := append(slice1, slice2...)
Удаление элементов / срезов
Если вам нужно удалить один или несколько элементов из среза или если вам нужно работать с дополнительным срезом другого существующего; вы можете использовать следующий метод.
В следующих примерах используется срез int, но он работает со всеми типами срезов.
Поэтому для этого нам нужен кусочек, из ведьмы мы удалим некоторые элементы:
slice := []int{1, 2, 3, 4, 5, 6}
// > [1 2 3 4 5 6]
Нам нужны также индексы элементов для удаления:
// index of first element to remove (corresponding to the '3' in the slice)
var first = 2
// index of last element to remove (corresponding to the '5' in the slice)
var last = 4
И поэтому мы можем «срезать» срез, удаляя нежелательные элементы:
// keeping elements from start to 'first element to remove' (not keeping first to remove),
// removing elements from 'first element to remove' to 'last element to remove'
// and keeping all others elements to the end of the slice
newSlice1 := append(slice[:first], slice[last+1:]...)
// > [1 2 6]
// you can do using directly numbers instead of variables
newSlice2 := append(slice[:2], slice[5:]...)
// > [1 2 6]
// Another way to do the same
newSlice3 := slice[:first + copy(slice[first:], slice[last+1:])]
// > [1 2 6]
// same that newSlice3 with hard coded indexes (without use of variables)
newSlice4 := slice[:2 + copy(slice[2:], slice[5:])]
// > [1 2 6]
Чтобы удалить только один элемент, просто нужно поместить индекс этого элемента в качестве первого И как последний индекс для удаления, просто так:
var indexToRemove = 3
newSlice5 := append(slice[:indexToRemove], slice[indexToRemove+1:]...)
// > [1 2 3 5 6]
// hard-coded version:
newSlice5 := append(slice[:3], slice[4:]...)
// > [1 2 3 5 6]
И вы также можете удалить элементы с начала среза:
newSlice6 := append(slice[:0], slice[last+1:]...)
// > [6]
// That can be simplified into
newSlice6 := slice[last+1:]
// > [6]
Вы также можете удалить некоторые элементы из конца среза:
newSlice7 := append(slice[:first], slice[first+1:len(slice)-1]...)
// > [1 2]
// That can be simplified into
newSlice7 := slice[:first]
// > [1 2]
Если новый фрагмент должен содержать точно такие же элементы, кроме первого, вы можете использовать одно и то же, но с
last := first-1
.
(Это может быть полезно в случае, если ваши индексы предварительно вычислены)
Длина и мощность
Ломтики имеют длину и емкость. Длина среза - это количество элементов, находящихся в данный момент на срезе, а емкость - это количество элементов, которое может удерживать срез перед перераспределением.
При создании среза с использованием встроенной функции make()
вы можете указать ее длину и, при необходимости, ее емкость. Если емкость явно не указана, это будет указанная длина.
var s = make([]int, 3, 5) // length 3, capacity 5
Вы можете проверить длину среза со встроенной функцией len()
:
var n = len(s) // n == 3
Вы можете проверить емкость с помощью встроенной функции cap()
:
var c = cap(s) // c == 5
Элементы, созданные командой make()
, устанавливаются в нулевое значение для типа элемента среза:
for idx, val := range s {
fmt.Println(idx, val)
}
// output:
// 0 0
// 1 0
// 2 0
Запустите его на play.golang.org
Вы не можете получить доступ к элементам за пределами длины среза, даже если индекс находится в пределах емкости:
var x = s[3] // panic: runtime error: index out of range
Однако, если пропускная способность превышает длину, вы можете добавлять новые элементы без перераспределения:
var t = []int{3, 4}
s = append(s, t) // s is now []int{0, 0, 0, 3, 4}
n = len(s) // n == 5
c = cap(s) // c == 5
Если вы добавляете к фрагменту, который не имеет возможности принимать новые элементы, базовый массив будет перераспределен для вас с достаточной пропускной способностью:
var u = []int{5, 6}
s = append(s, u) // s is now []int{0, 0, 0, 3, 4, 5, 6}
n = len(s) // n == 7
c = cap(s) // c > 5
Поэтому, как правило, хорошей практикой является выделение достаточной емкости при первом создании среза, если вы знаете, сколько места вам нужно, чтобы избежать ненужных перераспределений.
Копирование содержимого из одного фрагмента в другой фрагмент
Если вы хотите скопировать содержимое среза в первоначально пустой срез, для его выполнения можно предпринять следующие шаги:
- Создайте срез источника:
var sourceSlice []interface{} = []interface{}{"Hello",5.10,"World",true}
- Создайте срез назначения с помощью:
- Длина = Длина источникаSlice
var destinationSlice []interface{} = make([]interface{},len(sourceSlice))
- Теперь, когда базовый массив целевого среза достаточно велик, чтобы разместить все элементы среза источника, мы можем приступить к копированию элементов с помощью встроенной
copy
:
copy(destinationSlice,sourceSlice)
Создание фрагментов
Ломтики - это типичный способ, с помощью которого программисты хранят списки данных.
Чтобы объявить переменную среза, используйте синтаксис []Type
.
var a []int
Чтобы объявить и инициализировать переменную среза в одной строке, используйте синтаксис []Type{values}
.
var a []int = []int{3, 1, 4, 1, 5, 9}
Другой способ инициализации среза - с помощью функции make
. Это три аргумента: Type
среза (или карты ), length
и capacity
.
a := make([]int, 0, 5)
Вы можете добавлять элементы в свой новый фрагмент, используя append
.
a = append(a, 5)
Проверьте количество элементов в вашем фрагменте, используя len
.
length := len(a)
Проверьте емкость вашего среза, используя cap
. Емкость - это количество элементов, которые в настоящее время выделены для хранения фрагмента. Вы всегда можете добавить к ломтику по мере того, как Go автоматически создаст для вас более крупный фрагмент.
capacity := cap(a)
Вы можете получить доступ к элементам в срезе, используя типичный синтаксис индексирования.
a[0] // Gets the first member of `a`
Вы также можете использовать цикл for
по срезам с range
. Первой переменной является индекс в указанном массиве, а вторая переменная - значение для индекса.
for index, value := range a {
fmt.Println("Index: " + index + " Value: " + value) // Prints "Index: 0 Value: 5" (and continues until end of slice)
}
Фильтрация среза
Чтобы фильтровать срез без выделения нового базового массива:
// Our base slice
slice := []int{ 1, 2, 3, 4 }
// Create a zero-length slice with the same underlying array
tmp := slice[:0]
for _, v := range slice {
if v % 2 == 0 {
// Append desired values to slice
tmp = append(tmp, v)
}
}
// (Optional) Reassign the slice
slice = tmp // [2, 4]
Нулевое значение среза
Нулевое значение среза равно nil
, которое имеет длину и емкость 0
. nil
срез не имеет базового массива. Но есть также не-nil-фрагменты длины и емкости 0
, например []int{}
или make([]int, 5)[5:]
.
Любой тип, который имеет значения nil, может быть преобразован в nil
фрагмент:
s = []int(nil)
Чтобы проверить, пустой ли срез, используйте:
if len(s) == 0 {
fmt.Ptintf("s is empty.")
}