Зрізи в Go схожі на масиви в інших мовах. Вони містять кілька елементів певного типу (або інтерфейсу).
Зрізи в Go базуються на масивах. Масиви мають фіксований розмір. Зріз же - це динамічно розмірне, гнучке подання елементів масиву.
Зріз записують як []T, де T - це тип елементів у зрізі:
var empty []int // an empty slice
withData := []int{0,1,2,3,4,5} // a slice pre-filled with some data
Можна отримати або встановити елемент за заданим індексом, що відраховується від нуля, використовуючи запис у квадратних дужках:
withData[1] = 5
x := withData[1] // x is now 5
Можна створити новий зріз з наявного зрізу, взявши діапазон елементів. Знову ж таки, використовуючи квадратні дужки, але вказуючи як початковий (включно), так і кінцевий (не включно) індекс. Якщо не вказати початковий індекс, він типово дорівнює 0. Якщо не вказати кінцевий індекс, він типово дорівнює довжині зрізу.
newSlice := withData[2:4]
// => []int{2,3}
newSlice := withData[:2]
// => []int{0,1}
newSlice := withData[2:]
// => []int{2,3,4,5}
newSlice := withData[:]
// => []int{0,1,2,3,4,5}
Можна додавати елементи до зрізу за допомогою функції append.
Нижче ми додаємо 4 і 2 до зрізу a.
a := []int{1, 3}
a = append(a, 4, 2)
// => []int{1,3,4,2}
append завжди повертає новий зріз, і коли ми просто хочемо додати елементи до наявного зрізу, зазвичай результат знову присвоюють тій самій змінній зрізу, яку ми передали першим аргументом, як це зроблено вище.
append також можна використати, щоб обʼєднати два зрізи:
nextSlice := []int{100,101,102}
newSlice := append(withData, nextSlice...)
// => []int{0,1,2,3,4,5,100,101,102}
Зазвичай функції в Go приймають лише фіксовану кількість аргументів. Однак у Go можна також писати варіативні функції.
Варіативна функція - це функція, яка приймає змінну кількість аргументів.
Якщо перед типом останнього параметра у визначенні функції стоїть трикрапка ..., тоді функція може приймати будь-яку кількість аргументів для цього параметра.
func find(a int, b ...int) {
// ...
}
У наведеній вище функції параметр b варіативний, і ми можемо передати b 0 або більше аргументів.
find(5, 6)
find(5, 6, 7)
find(5)
Варіативний параметр має бути останнім параметром функції.
Варіативні функції працюють так: змінну кількість аргументів перетворюють на зріз типу варіативного параметра.
Ось приклад реалізації варіативної функції.
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
return
}
}
fmt.Println(num, "not found in ", nums)
}
func main() {
find(89, 90, 91, 95)
// =>
// type of nums is []int
// 89 not found in [90 91 95]
find(45, 56, 67, 45, 90, 109)
// =>
// type of nums is []int
// 45 found at index 2 in [56 67 45 90 109]
find(87)
// =>
// type of nums is []int
// 87 not found in []
}
У рядку find(89, 90, 91, 95) наведеної вище програми змінною кількістю аргументів функції find є 90, 91 і 95.
Функція find приймає варіативний параметр типу int після num.
Отже, компілятор перетворить ці три аргументи на зріз типу int []int{90, 91, 95} і потім передасть його функції find як nums.
Іноді в нас уже є зріз, і ми хочемо передати його варіативній функції.
Це можна зробити, передавши зріз, а після нього ....
Це вкаже компілятору використати зріз як є всередині варіативної функції.
Крок, описаний вище, де створюється зріз, у цьому випадку просто пропускається.
list := []int{1, 2, 3}
find(1, list...) // "find" defined as shown above
Як майбутня фокусниця, Еліз має потренуватися в основах. У неї є стос карт, з якими вона хоче працювати.
Щоб трохи спростити собі справу, вона використовує лише карти від 1 до 10.
Практикуючись зі своїми картами, Еліз любить починати з трьох улюблених карт колоди: 2, 6 і 9.
Напишіть функцію FavoriteCards, яка повертає зріз із цими картами в такому порядку.
cards := FavoriteCards()
fmt.Println(cards)
// Output: [2 6 9]
Поверніть карту на позиції index із заданого стосу.
card := GetItem([]int{1, 2, 4, 1}, 2) // card == 4
Якщо індекс виходить за межі (тобто якщо він відʼємний або після кінця стосу), потрібно повернути -1:
card := GetItem([]int{1, 2, 4, 1}, 10) // card == -1
У Go за домовленістю замість повернення значення «поза межами» повертають помилку.
Тут значенням «поза межами» є -1, коли на цьому місці має бути додатне ціле число.
Повертаючи помилку, ідіоматично повертати разом із нею zero value.
Повернення помилки разом із належним значенням буде розглянуто в одній із наступних вправ.
Замініть карту на позиції index на надану нову карту й поверніть змінений стос.
Зауважте, що це змінить вхідний зріз, і саме така поведінка очікується.
index := 2
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 6 1]
Якщо індекс виходить за межі (тобто якщо він відʼємний або після кінця стосу), потрібно додати нову карту в кінець стосу:
index := -1
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 4 1 6]
Додайте карту (або карти), указану в параметрі value, на верхівку стосу.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice, 5, 1)
fmt.Println(cards)
// Output: [5 1 3 2 6 4 8]
Якщо для параметра value не передано жодного аргументу, результат дорівнює початковому зрізу.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Вилучіть карту на позиції index зі стосу й поверніть стос.
Зауважте, що це може змінити вхідний зріз, і це нормально.
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 2)
fmt.Println(cards)
// Output: [3 2 4 8]
Якщо індекс виходить за межі (тобто якщо він відʼємний або після кінця стосу), потрібно залишити стос без змін:
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 11)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Зареєструйтеся на Exercism, щоб вивчати й опановувати Go, а також 34 концепції165 вправ та справжнє наставництво від людей, і все це безкоштовно.