Проверяет понимание передачи срезов в Go по ссылке и влияния изменений на исходный массив.
Срез (slice) в Go — это дескриптор, который содержит три поля: указатель на первый элемент массива, длину и емкость. Когда вы передаете срез в функцию, копируется именно этот дескриптор, но указатель внутри копии указывает на тот же самый массив. Поэтому изменения элементов массива через срез будут видны и в вызывающем коде.
Если внутри функции вы меняете элемент среза, например s[0] = 100, то это изменение затрагивает общий массив. После возврата из функции исходный срез увидит новое значение. Это часто используется для модификации данных без явного возврата.
func modify(s []int) {
s[0] = 100
}
func main() {
arr := []int{1, 2, 3}
modify(arr)
fmt.Println(arr) // [100 2 3]
}Если внутри функции вы используете append, то поведение зависит от емкости. Если емкости достаточно, append изменяет элементы в том же массиве, и длина исходного среза не меняется, но элементы могут быть перезаписаны. Если емкости не хватает, создается новый массив, и изменения не затрагивают исходный срез.
func appendToSlice(s []int) {
s = append(s, 4)
s[0] = 99
}
func main() {
arr := []int{1, 2, 3}
appendToSlice(arr)
fmt.Println(arr) // [1 2 3] или [99 2 3] в зависимости от емкости
}Понимание этого механизма важно для написания эффективного кода. Если вы хотите изменить срез внутри функции и сохранить изменения, нужно либо возвращать новый срез, либо передавать указатель на срез. Это особенно актуально при работе с большими структурами данных, чтобы избежать лишних копирований.
Срезы в Go передаются по значению, но разделяют массив. Изменение элементов видно снаружи, а изменение длины — нет. Для модификации длины среза используйте возврат значения или указатель на срез.