Если передать слайс в функцию и добавить элемент, будут ли изменения видны в вызывающей функции
Что проверяют
Понимаете ли вы, что слайс это структура из трёх полей, которая копируется при передаче. Классический вопрос-ловушка.
Как отвечать
Правильный ответ: нет, добавление элемента через append в вызывающей функции не видно.
Слайс это заголовок: указатель на массив, длина и ёмкость. При передаче в функцию копируется сам заголовок. Указатель в копии тот же, поэтому изменение существующих элементов по индексу видно снаружи. А append меняет длину, то есть поле копии, и возвращает новый заголовок, который остаётся внутри функции.
func addWrong(s []int) { s = append(s, 4) } // снаружи ничего
func setOk(s []int) { s[0] = 100 } // снаружи видно
func addRight(s []int) []int { return append(s, 4) } // так правильноОтдельно стоит рассказать про коварный случай: если ёмкости хватает, append пишет в тот же массив. Тогда снаружи длина прежняя, но элемент за её пределами уже перезаписан, и другой слайс, ссылающийся на тот же массив, увидит изменение. Это источник ошибок с общими массивами после s[:2].
Как делать правильно: возвращать новый слайс из функции (так устроен и сам append), либо передавать указатель *[]int, если менять нужно на месте. Для защиты от неожиданного разделения памяти есть slices.Clone и трёхиндексная нарезка s[a:b:b], которая ограничивает ёмкость.
Где спотыкаются
Ожидают поведения как у карты или канала: те действительно ссылочные, и изменения видны.
Меняют элементы среза, полученного через s[:2], и портят исходный массив.
Копируют слайс присваиванием и считают, что получили независимую копию данных.