Go Academy · Урок

Срезы: динамические списки

make, append, copy, len и cap

Урок 2 из 413 шагов

«Срезы: динамические списки» — бесплатный урок Go Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Что такое срез

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

  • Срезы являются ссылочными типами — несколько срезов могут совместно использовать один базовый массив
  • Для большинства задач, связанных со списками, в Go используют срезы, а не массивы

Литералы срезов и создание срезов

Создавайте срезы с помощью литерала или make:

package main
import "fmt"

func main() {
    nums := []int{1, 2, 3, 4, 5}      // literal
    strs := make([]string, 3)          // len=3, cap=3, zero values
    buf  := make([]byte, 0, 64)        // len=0, cap=64
    fmt.Println(nums, strs, len(buf), cap(buf))
}

Длина и ёмкость

len возвращает текущее количество элементов в срезе. cap возвращает ёмкость базового массива, начиная от указателя на начало среза.

package main
import "fmt"

func main() {
    s := make([]int, 3, 8)
    fmt.Println(len(s)) // 3
    fmt.Println(cap(s)) // 8
}

Добавление: увеличение среза

append добавляет элементы в срез, выделяя новый базовый массив, когда текущей ёмкости недостаточно:

package main
import "fmt"

func main() {
    s := []int{1, 2, 3}
    s = append(s, 4, 5)
    s = append(s, []int{6, 7, 8}...)
    fmt.Println(s) // [1 2 3 4 5 6 7 8]
}

Получение части среза

Используйте синтаксис [low:high], чтобы создать подсрез (он совместно использует базовый массив):

package main
import "fmt"

func main() {
    a := []int{0, 1, 2, 3, 4, 5}
    b := a[1:4]   // [1 2 3]
    c := a[:3]    // [0 1 2]
    d := a[3:]    // [3 4 5]
    fmt.Println(b, c, d)
}

Копирование: независимые срезы

copy копирует элементы между срезами и возвращает количество скопированных элементов. Приёмник и источник не используют общую память:

package main
import "fmt"

func main() {
    src := []int{1, 2, 3}
    dst := make([]int, len(src))
    n := copy(dst, src)
    dst[0] = 99
    fmt.Println(src, dst, n) // [1 2 3] [99 2 3] 3
}

Нулевой и пустой срезы

Нулевой срез не имеет базового массива. У пустого среза есть базовый массив, но длина равна 0. У обоих len == 0:

package main
import "fmt"

func main() {
    var nilSlice []int
    emptySlice  := []int{}
    fmt.Println(nilSlice  == nil) // true
    fmt.Println(emptySlice == nil) // false
    fmt.Println(len(nilSlice), len(emptySlice)) // 0 0
    nilSlice = append(nilSlice, 1) // safe!
}

Удаление элемента

В Go нет встроенной функции удаления для срезов. Идиоматичный подход использует добавление:

package main
import "fmt"

func main() {
    s := []int{1, 2, 3, 4, 5}
    i := 2 // delete index 2
    s = append(s[:i], s[i+1:]...)
    fmt.Println(s) // [1 2 4 5]
}

Вставка элемента

Вставляйте элемент в позицию i, сочетая добавление и получение части среза:

package main
import "fmt"

func main() {
    s := []int{1, 2, 4, 5}
    i := 2
    s = append(s[:i+1], s[i:]...)
    s[i] = 3
    fmt.Println(s) // [1 2 3 4 5]
}

Важный нюанс срезов: общий базовый массив

Подсрезы используют общий базовый массив — изменение одного влияет на другой, пока не произойдёт перераспределение памяти:

package main
import "fmt"

func main() {
    a := []int{1, 2, 3, 4}
    b := a[:2]   // shares backing array
    b[0] = 99
    fmt.Println(a) // [99 2 3 4] — a is changed!
}

Быстрая проверка

Что возвращает операция добавления?

Итоги: срезы

Основные выводы:

  • Срезы = указатель + длина + ёмкость; они представляют собой оболочку над массивами
  • Используйте make, чтобы заранее выделить ёмкость
  • Всегда присваивайте результат append
  • copy создаёт независимые срезы
  • Помните об общих базовых массивах подсрезов

Задание для практики

Создайте с помощью make срез из 5 целых чисел, добавьте ещё три значения, затем скопируйте его в новый срез и измените копию, не затрагивая оригинал. Выведите оба среза.

Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Срезы: динамические списки» бесплатный?

Да — полный текст урока «Срезы: динамические списки» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Срезы: динамические списки»?

make, append, copy, len и cap Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Срезы: динамические списки»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Массивы: коллекции фиксированной длины
  2. Срезы: динамические списки
  3. Отображения: хранилища пар ключ-значение
  4. Итерация по коллекциям с range
← Назад к Go Academy