Go в примерах: Срезы (Slices)

Срезы ключевой тип данных в Go, дающий более мощный интерфейс для работы с последовательностями, чем массивы.

package main
import "fmt"
func main() {

Срез это часть массива. Как и массивы срезы индексируются и имеют длину. В отличии от массивов, их длину можно изменить. Для создания пустого среза с не нулевой длиной воспользуйтесь встроенной функцией make. В этом примере мы создали срез из строк с размером среза в 3 элемента (инициализированных нулевыми значениями).

    s := make([]string, 3)
    fmt.Println("emp:", 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, которая возвращает срез содержащий 1 или более новых значений. Обратите внимание, что мы должны принять возвращаемое функцией append значение - таким образом мы получаем новое значение среза.

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

Срезы можно копировать. В этом примере мы создали пустой срез c той же самой длины что и s и скопировали содержимое из s в c.

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

Срезы поддерживают “slice”-оператор с синтаксисом slice[low:high]. Например, здесь мы получаем срез элементов s[2], s[3], и s[4].

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

Здесь делается срез элементов от s[0] до 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)

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

    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
emp: [  ]
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]
2d:  [[0] [1 2] [2 3 4]]

Почитайте этот замечательный пост написанный командой разработчиков Go, для лучшего представления о дизайне срезов и их реализации.

Теперь, когда мы познакомились с массивами и срезами, давайте взглянем на другой ключевой тип данных в Go: карты (maps).

Следующий пример: Направления каналов (Channel Directions).