Изменится ли слайс на вызывающей стороне при передаче и модификации в функции в Go
Что проверяют
Понимаете ли вы, что слайс это описатель, а данные общие. Вопрос с подвохом: ответ зависит от того, что именно делает функция.
Как отвечать
Слайс передаётся по значению: копируется структура из указателя, длины и ёмкости. Но указатель в копии тот же, значит массив общий.
Отсюда два разных исхода:
Изменение элемента видно снаружи.
func zero(s []int) { s[0] = 0 }
a := []int{1, 2, 3}
zero(a) // a стал [0 2 3]Изменение самого слайса снаружи не видно.
func add(s []int) { s = append(s, 4) }
a := []int{1, 2, 3}
add(a) // a остался [1 2 3]Причина: append меняет локальную копию описателя (её длину или вовсе указатель на новый массив), а переменная вызывающего продолжает указывать на старое.
И самый коварный случай: если ёмкости хватало, append внутри функции запишет значение в общий массив. Тогда снаружи длина не изменится, но элемент за пределами длины окажется перезаписан, и это видно, если потом сделать append уже снаружи.
Отсюда практика: функция, изменяющая слайс, возвращает его (func add(s []int) []int), либо принимает указатель. Именно поэтому и сам append устроен как возвращающий значение, а не как изменяющий на месте.
Где спотыкаются
Отвечают однозначно «да» или «нет», не различая изменение элемента и изменение слайса.
Забывают присвоить результат append.
Не знают про перезапись общего массива при достаточной ёмкости.
Считают, что передача слайса копирует данные.