Все вопросы

22 Коллекции

Когда append перевыделяет массив?

append дописывает элементы в хвост. Если len + сколько_добавили не больше cap, элементы пишутся в тот же массив. Если ёмкости не хватает, рантайм выделяет новый массив, копирует старые элементы и возвращает заголовок уже на него. Старый slice при этом не обновляется сам — результат нужно сохранить: s = append(s, x).

В примере у a ёмкость ровно 2, поэтому третий элемент не влезает. b получает новый массив. Запись b[0] = 9 не меняет a, и сравнение адресов первых элементов даёт false.

Пока ёмкость общая, правка элемента через один slice видна в другом. Поэтому функцию, которая и добавляет элементы, и меняет старые, проектируют так, чтобы вызывающий пользовался только возвращённым slice.

Пример

Go

старый срез не видит новый массив

package main

import "fmt"

func main() {
    a := make([]int, 2, 2)
    a[0], a[1] = 1, 2

    b := append(a, 3)
    b[0] = 9

    fmt.Println("a", a)
    fmt.Println("b", b)
    fmt.Println("делят массив:", &a[0] == &b[0])
}