Что покажут вывод cap и строки x и y после append здесь?
Приведите выведенные ёмкости, затем проследите, как append(y, "z") влияет на x и y.
func slicesSharedMemAppend() {
x := []string{"a", "b", "c", "d"}
y := x[:2]
fmt.Println(cap(x), cap(y))
y = append(y, "z")
fmt.Println("x:", x)
fmt.Println("y:", y)
}
Определите вывод.
Выведет 4 4, затем x: [a b z d] и y: [a b z]. У y := x[:2] len 2, но он наследует cap 4 до конца backing array x, поэтому у append(y, "z") есть запас, и он пишет в общий x[2], перезаписывая c вместо аллокации.
- ✗Думать, что
cap(y)равен 2 — reslice наследует cap до конца массива родителя, поэтому он 4 - ✗Считать, что
appendвсегда аллоцирует — при запасе cap он перезаписывает общий элемент на месте - ✗Забывать, что длина
xне меняется — лишь значениеx[2]становитсяz
- →Как
y := x[:2:2]изменитcap(y)и результатappend? - →Почему длина
xостаётся 4, хотяx[2]был перезаписан?
Что выведет код?
x := []string{"a", "b", "c", "d"}
y := x[:2]
fmt.Println(cap(x), cap(y))
y = append(y, "z")
Вывод
4 4
x: [a b z d]
y: [a b z]
Почему append портит x
y := x[:2] имеет len 2, но ёмкость наследуется до конца backing array x: cap(y) == 4. Поэтому первая строка печатает 4 4.
У append(y, "z") есть запас (len 2 < cap 4), поэтому он не аллоцирует — пишет "z" в общий backing array по индексу 2, перезаписывая x[2] (было c). Длина x не меняется (заголовок x отдельный), но значение x[2] теперь z → x = [a b z d]. Возвращённый y имеет len 3: [a b z].
Чтобы append гарантированно аллоцировал и не трогал x, ограничьте ёмкость полным выражением среза: y := x[:2:2] (тогда cap(y) == 2).