Как функция append меняет срезы и ссылки

Первый вывод — [{0} {0}] [{100} {0} {0}]. Во втором общем случае важна вместимость listB: при её достаточности оба среза увидят 200.

Короткий ответ

Что ответить на собеседовании

Первый вывод — [{0} {0}] [{100} {0} {0}]. Во втором общем случае важна вместимость listB: при её достаточности оба среза увидят 200.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо предсказать, какие данные будут выведены программой, учитывая особенности работы срезов, указателей и возможного копирования при вызове append.

type account struct {
    value int
}

func main() {
    listA := make([]account, 0, 2)
    listA = append(listA, account{})
    listA = append(listA, account{})
    listB := append(listA, account{})

    ptr := &listB[0]
    ptr.value = 100

    fmt.Println(listA, listB)

    listA = append(listB, account{})
    ptr.value += 100

    fmt.Println(listA, listB)
}

Ответ

Первый вывод — [{0} {0}] [{100} {0} {0}]. Во втором общем случае важна вместимость listB: при её достаточности оба среза увидят 200.

Первое добавление третьего элемента превышает capacity(listA) = 2, поэтому listB получает другой массив. ptr указывает уже на его первый элемент, не на исходный listA.

При обычном росте capacity(listB) хватает на четвёртый элемент: второй вывод будет [{200} {0} {0} {0}] [{200} {0} {0}]. Но если новая вместимость была ровно 3, следующий append создаст ещё один массив: listA сохранит 100, а ptr изменит только listB до 200. Стратегия роста capacity не является гарантией языка; адрес ptr не перенаправляется автоматически на новый массив.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее