Материал проходит вычитку — возможны неточности.
Урок 5 из 118

copy и правка на месте

Аня оставила на ревью импорта комментарий: зачем плодить лишние копии, если можно править данные на месте. Миша переписал фильтрацию на правку по месту, и Аня приняла правку с первого раза.

Главная мысль

copy — прямой и самый явный способ получить независимую копию данных слайса; а срез nums[:0] с append позволяет менять слайс на месте, без аллокаций.

Copy

Go

copy копирует элементы и возвращает количество скопированных — минимум из длин источника и приёмника. Присваивание копирует только заголовок, а copy — сами данные. Если нужно «отвязать» слайс от исходного массива, копируй в новый слайс.

Фильтрация на месте

Классика — отобрать элементы, не выделяя новую память:

func filterInPlace(nums []int, keep func(int) bool) []int {
    out := nums[:0]
    for _, n := range nums {
        if keep(n) {
            out = append(out, n)
        }
    }
    return out
}

nums[:0] — тот же массив, но с длиной ноль. append дописывает отобранные элементы поверх исходных, а лишние в конце отбрасываются изменением длины. Функция переиспользует память исходного слайса и не аллоцирует ничего нового.

Range копирует заголовок

range по слайсу копирует только заголовок, поэтому изменения элементов в теле цикла видны сразу. Переменная v внутри range — копия элемента, писать в неё бесполезно:

for i, v := range s {
    v = v * 2        // меняет копию, не слайс
    s[i] = s[i] * 2  // меняет слайс
}
В следующем уроке

Вы узнаете:

  • как удалить элемент из слайса
  • чем slices.Clone(s) отличается от copy
  • как сравнить производительность copy и ручного цикла
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

При импорте записи перекладывают между буферами разной длины: dst := make([]int, 4); n := copy(dst, []int{1, 2, 3}). Чему равно n?

Вопрос 2 из 3

Чем copy(dst, src) отличается от простого присваивания dst := src?

Вопрос 3 из 3

В цикле for i, v := range s запись v = v * 2: что произойдёт?

Итоги

copy — независимая копия; nums[:0] + append — правка на месте без аллокаций; в range переменная — копия элемента.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки