Golang, как передаются слайсы в функцию, по ссылке или по значению?
В Go слайсы передаются по значению, но при этом ведут себя как ссылки. Этот механизм можно понять лучше, если разобраться, как устроены слайсы.
Структура слайсов в Go
Слайс в Go — это структура, состоящая из трех полей:
- Указатель на массив (под капотом у слайса всегда есть массив, на который он указывает).
- Длина слайса — количество элементов, которые доступны в слайсе.
- Вместимость слайса — максимальное количество элементов, которые могут быть добавлены без перераспределения памяти.
Когда слайс передается в функцию, создается копия структуры слайса (по значению). Однако эта копия содержит указатель на тот же массив данных, что и оригинал. Поэтому изменения, касающиеся самих элементов слайса (например, slice[0] = 42
), будут видны и за пределами функции, так как оба слайса ссылаются на один и тот же массив данных.
Важное исключение: append
Когда используется функция append
, Go может изменить внутренний массив, если текущей вместимости не хватает. При этом append
вернет новый слайс с новым указателем на массив. Если результат append
не присвоен обратно в переменную, изменения не сохранятся вне функции.
Пример
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import "fmt" func modifySlice(s []int) { s[0] = 99 // Изменение элемента, видно снаружи s = append(s, 42) // `append` создает новый слайс, так как не хватает вместимости fmt.Println(s) // Выводит: [99 2 3 42] } func main() { slice := []int{1, 2, 3} modifySlice(slice) fmt.Println(slice) // Выводит: [99 2 3] } |
- Изменение
s[0] = 99
видно вmain
, так какslice
иs
указывают на один массив. append(s, 42)
создает новый массив (так как не хватает вместимости), но результат не присваивается обратно вslice
, поэтомуslice
вmain
не меняется.
Recommended Posts
Golang Sarama: настройка Partitioner
20.03.2024