Go за Прикладом: Зрізи

slice або зріз одним з найважливіших типів даних у GO, Він представляє собою зручний інтерфейс до послідовностей, основою яких є інший тип даних - масив.

package main
import (
    "fmt"
    "slices"
)
func main() {

На відміну від масивів, зрізи типізовані лише елементами які вони містять (а не числом елементів) Не ініціалізований зріз дорівнюю nil і має довжину 0.

    var s []string
    fmt.Println("uninit:", s, s == nil, len(s) == 0)

На відміну від, масиву, зріз обмежений лише типом елементів який він зобов’язуються зберігати (масиви ж, надодачу обмежені кількостю елементів). Створити пустий зріз, не нульової довжини можливо скориставшись функцією make. Зверніть увагу на приклад створення зрізу рядків довжиною в 3 елементи (усі строки початково ініціалізовані з нульовим значенням).

    s = make([]string, 3)
    fmt.Println("emp:", s, "len:", len(s), "cap:", cap(s))

Встановлюємо та звертаємось до значень зрізу аналогічно масивам.

    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("set:", s)
    fmt.Println("get:", s[2])

len поверне довжину зрізу.

    fmt.Println("len:", len(s))

На додачу, до базових операцій, зрізи підтримують ще кілька додаткових - що робить їх значно привабливішими, ніж масиви. Перша з цих операцій - це функція append, що поверне зріз, який зберігатиме одне або більше нових значень. Зауважимо, потрібно присвоїти значення змінні зрізу, що повертається з append - оскільки ми можемо отримати новий зразок зрізу (новий instance).

    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println("apd:", s)

Зрізи також можуть бути скопійовані. В цьому прикладі ми створимо новий зріз c аналогічного типу та довжини що і s, після чого використовуючи copy скопіюємо значення s в c.

    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy:", c)

Зрізи підтримують оператор “зрізання” за допомогою наступного синтаксису зріз[з_ніжного_індексу:до_верхнього_індексу]. В нашому прикладі, ця операція отримає зрізs, що складається з елементів s[2], s[3] та s[4] та представить його як l.

    l := s[2:5]
    fmt.Println("sl1:", l)

Приклад зрізання усіх елементів до (але виключаючи) s[5].

    l = s[:5]
    fmt.Println("sl2:", l)

Приклад зрізання усіх елементів з (але включаючи) s[2].

    l = s[2:]
    fmt.Println("sl3:", l)

Нам дозволяється декларувати та ініціалізувати значення змінних в зрізі одним рядком (так само і масиви).

    t := []string{"g", "h", "i"}
    fmt.Println("dcl:", t)

Пакет slices містить низку корисних функцій для зрізів.

    t2 := []string{"g", "h", "i"}
    if slices.Equal(t, t2) {
        fmt.Println("t == t2")
    }

Зрізи можуть бути скомпоновані в багатовимірні структури даних. Довжина внутрішніх зрізів буде варіюватись, на відміну від багатовимірних масивів.

    twoD := make([][]int, 3)
    for i := 0; i < 3; i++ {
        innerLen := i + 1
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}

Хоч зрізи і іншого типу ніж масиви, відображатимуться вони однаково, під час друку за допомогою fmt.Println.

$ go run slices.go
uninit: [] true true
emp: [  ] len: 3 cap: 3
set: [a b c]
get: c
len: 3
apd: [a b c d e f]
cpy: [a b c d e f]
sl1: [c d e]
sl2: [a b c d e]
sl3: [c d e f]
dcl: [g h i]
t == t2
2d:  [[0] [1 2] [2 3 4]]

Рекомендуємо прочитати чудовий пост (за авторства команди розробників Go), щоб отримати докладну інформацію про розробку та застосування зрізів в Go.

Після того як ми бачили масиви та зрізи, звернемо увагу на іншу важливу структуру даних в Go — мапи.

Наступний приклад: Мапи.