Загрузка…
Загрузка…
Go · junior · сложность 3
В Go slice — это не сам массив, а легкий «дополнительный» дескриптор части массива. Именно поэтому поведение slice отличается от обычного копирования массива и часто вызывает ошибки в интервью и реальном коде.
slice:slice концептуально состоит из трех частей:
Указатель на базовый массив (ptr)
Длина (len) — сколько предметов доступно сейчас.
Емкость (cap) — сколько элементов доступно до предела
базовый массив
То есть slice хранит метаданные о регионе в памяти, а не дублирует все элементы.
slice функции:Копируется заголовок slice (ptr/len/cap), а не весь массив.
Обе стороны (вызывающий и вызывающий) изначально смотрят на один и тот же базовый массив.
Изменение элементов по индексу (s[i] = ...) в функции обычно
виден снаружи, поскольку данные общего массива изменяются.
Изменение самого заголовка (s = s[:n], s = append(...)) в функции
не меняет заголовок в вызывающем объекте, если вы не вернете новый slice.
append:Если во время append достаточно cap, запись переходит в ту же базу.
array.
Если cap отсутствует, среда выполнения выделяет новый массив, копирует туда данные,
и локальный slice в функции начинает ссылаться на другую память.
Итак, после append функция уже может работать с новым массивом, а старый slice останется снаружи, если не будет возвращено новое значение.
Хотите изменить элементы - можете передать slice как есть.
Хотите изменить длину/емкость или результат append — верните обновленный
slice из функции (или передать указатель на slice, если это действительно
архитектурно оправдано).
package main
import "fmt"
func grow(s []int) {
s = append(s, 99) // змінюємо локальний заголовок slice
}
func mutate(s []int) {
s[0] = 42 // змінюємо спільний базовий масив
}
func main() {
s := []int{1, 2, 3}
mutate(s)
grow(s)
fmt.Println(s) // [42 2 3], append у grow не змінив заголовок у викликачі
}В Go slice — это не сам массив, а легкий «дополнительный» дескриптор части массива.