Golang tricks: работа слайсов
Что будет выводить функция fmt.Println(slice) в каждом случае и почему:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
func main() { slice := make([]int, 3, 4) prikol(slice) fmt.Println(slice) // вопрос: Изменился ли слайс? prikol(slice) fmt.Println(slice) // вопрос: Изменился ли слайс? prikol(slice[:1]) fmt.Println(slice) // вопрос: Изменился ли слайс? } func prikol(slice []int) { slice = append(slice, 1) } |
Разберем, что происходит на каждом этапе этого кода.
Что делает make([]int, 3, 4)
Эта строка создает слайс slice с:
- длиной 3 (
len(slice) = 3), - вместимостью 4 (
cap(slice) = 4), - инициализированный значениями
[0, 0, 0](по умолчанию дляint).
Детали функции prikol
Функция prikol:
- принимает слайс в качестве аргумента,
- делает
appendс добавлением числа1в конец слайса.
Здесь важно понимать, что append работает по-разному в зависимости от вместимости слайса:
- Если текущая вместимость слайса позволяет вместить новый элемент,
appendдобавит элемент в конец текущего массива, на который указывает слайс, и вернет тот же массив. - Если вместимость исчерпана,
appendсоздаст новый массив с удвоенной вместимостью, скопирует данные из старого массива в новый и вернет новый массив.
Но! Поскольку append возвращает новый слайс, то для того чтобы результат сохранился, его нужно присвоить обратно. В функции prikol этого не делается, что играет решающую роль.
Анализ по строкам
- Первая строка
prikol(slice)В этой строке функцияprikolполучает копию слайсаslice:appendдобавляет1, и полученный слайс[0, 0, 0, 1]создается с вместимостью 4.- Но
slice = append(slice, 1)присваивается только внутриprikol, без влияния на исходныйsliceвmain.
В итоге внешний
sliceне меняется и остается[0, 0, 0].12fmt.Println(slice) // Выводит: [0 0 0] - Вторая строка
prikol(slice)Повторный вызовprikol(slice)снова работает по аналогии с первым:- Внутри
prikolснова создается новый слайс[0, 0, 0, 1], но изменения не передаются обратно вmain.
Поэтому снова внешний
sliceостается неизменным и равен[0, 0, 0].12fmt.Println(slice) // Выводит: [0 0 0] - Внутри
- Третья строка
prikol(slice[:1])Здесь начинается самое интересное:- В
prikolпередается слайсslice[:1], который имеет длину 1 и емкость 4 (так как он «видит» оставшуюся часть массива). - Теперь
append(slice, 1)добавляет1в позицию[1], и, поскольку это тот же базовый массив, изменение отражается наsliceвmain.
В результате после третьего вызова
sliceвmainстановится[0, 1, 0]. - В
Recommended Posts
Golang map и Swiss Table
16.03.2025
