Разделяемый базовый массив, copy и подсрезы
Содержание курса
make и copy: создание независимой копии среза
Чтобы получить срез с собственным базовым массивом, нужно сначала выделить память — через make([]T, n) — и затем перенести элементы через copy. Ни одно из этих действий само по себе не даёт полного результата: make([]T, n) создаёт срез длины n, заполненный нулевыми значениями типа T — это не nil-срез, а реальный массив из нулей; данные src в нём появятся только после copy. А copy без предварительно выделенного dst просто некуда писать.
package main
import "fmt"
func main() {
src := []int{10, 20, 30, 40, 50}
dst := make([]int, len(src)) // срез длины 5, элементы пока все равны 0
n := copy(dst, src) // копирует min(len(dst), len(src)) элементов
fmt.Println("скопировано:", n) // 5
fmt.Println("dst:", dst) // [10 20 30 40 50]
dst[0] = 999
fmt.Println("src после изменения dst:", src) // [10 20 30 40 50] — не изменился
}
copy возвращает количество скопированных элементов — это всегда min(len(dst), len(src)). Если dst короче src, скопируется только то, что влезает; остаток src отбрасывается. Если dst длиннее — лишние позиции останутся нулями. Возвращаемое число редко нужно сохранять в переменную, но важно понимать: именно оно говорит, сколько элементов реально перешло.
После copy у dst и src разные базовые массивы. Запись dst[0] = 999 не затрагивает src — что и подтверждает последний fmt.Println.
Одно важное уточнение: сам copy не выделяет память. Если написать var dst []int; copy(dst, src), copy честно скопирует ноль элементов, потому что len(dst) == 0. Память нужно выделить явно через make до вызова copy.
Граница применимости. Для []int — как в примере выше — отдельный базовый массив даёт полную независимость: изменение любого элемента через dst не видно через src и наоборот. Это работает, потому что int копируется как значение. copy всегда копирует элементы именно как значения. Если элементы сами содержат указатели, срезы или map, то скопируется ссылка, а не объект, на который она указывает — оба среза будут разделять вложенные данные. Глубокое копирование таких структур в рамках этого урока не рассматривается.
