Что выведут три строки Println после этих append?
Два перекрывающихся среза передаются в функцию, которая делает append к каждому. Определите три выведенные строки и объясните, почему массив и срезы вызывающей стороны затронуты (или нет).
func main() {
arr := []int{1, 2, 3, 4, 5}
slice1 := arr[1:] // {2,3,4,5} len=4 cap=4
slice2 := slice1[1:3] // {3,4} len=2 cap=3
ModifySlice(slice1)
ModifySlice(slice2)
fmt.Println("Original array:", arr) // ?
fmt.Println("Slice1:", slice1) // ?
fmt.Println("Slice2:", slice2) // ?
}
func ModifySlice(slice []int) {
slice = append(slice, 6, 7)
}
Определите вывод.
Все три выводят исходные значения — [1 2 3 4 5], [2 3 4 5], [3 4]. У slice1 cap равен 4, у slice2 — 3, поэтому добавление двух элементов переполняет обе ёмкости. Каждый append выделяет новый backing array и переприсваивает лишь локальную копию заголовка, поэтому заголовки вызывающей стороны и arr этого не видят.
- ✗Считать, что
appendвсегда меняет backing array вызывающей стороны — он пишет на месте только при запасеcap - ✗Забывать, что переприсваивание в
appendзатрагивает лишь локальную копию заголовка в параметре, а не переменную вызывающей стороны - ✗Неверно считать ёмкость
slice2— уslice1[1:3]capравен 3, а не 2, поэтому дваappendвсё равно переполняют
- →Если бы у
slice2capбыл 4 вместо 3, какая строкаPrintlnизменилась бы и почему? - →Как изменился бы вывод, если бы
ModifySliceвозвращала срез, а вызывающая сторона переприсваивала его?
Что выведет этот код?
package main
import "fmt"
func main() {
arr := []int{1, 2, 3, 4, 5}
slice1 := arr[1:] // {2,3,4,5} len=4 cap=4
slice2 := slice1[1:3] // {3,4} len=2 cap=3
ModifySlice(slice1)
ModifySlice(slice2)
fmt.Println("Original array:", arr) // ?
fmt.Println("Slice1:", slice1) // ?
fmt.Println("Slice2:", slice2) // ?
}
func ModifySlice(slice []int) {
slice = append(slice, 6, 7) // результат присваивается локальному параметру
}
Вывод
Original array: [1 2 3 4 5]
Slice1: [2 3 4 5]
Slice2: [3 4]
Почему ничего не изменилось
slice1 указывает на arr[1] с len=4, cap=4; slice2 — на arr[2] с len=2, cap=3.
Внутри ModifySlice оба append добавляют два элемента и превышают cap:
slice1:len 4 + 2 = 6 > cap 4→ runtime выделяет новый backing array.slice2:len 2 + 2 = 4 > cap 3→ тоже новый backing array.
append возвращает новый заголовок, но он присваивается параметру slice — локальной копии. Заголовок вызывающей стороны (slice1 / slice2) и общий arr остаются прежними. Поскольку оба append реаллоцировали, в arr вообще не записывается ни один элемент.
⚠️ Ловушка: если бы запас cap был, append записал бы 6, 7 на месте в общий arr (изменив соседние индексы), но переменная-срез вызывающей стороны всё равно сохранила бы старый len. Здесь обе записи ушли в свежие массивы.