Ответ
В Go все передается по значению. Однако некоторые типы ведут себя как ссылки, потому что само значение, которое копируется, является дескриптором (или заголовком), содержащим указатель на базовую структуру данных. Такие типы принято называть ссылочными.
К ним относятся:
- Срезы (
[]T
): Копируется структура, содержащая указатель на базовый массив, а также длину (len
) и ёмкость (cap
). - Мапы (
map[K]V
): Копируется указатель на структуру, описывающую мапу в памяти. - Каналы (
chan T
): Копируется указатель на внутреннюю структуру канала. - Функции: Копируется указатель на определение функции.
- Интерфейсы: Копируется структура из двух указателей: на информацию о типе и на сами данные.
- *Указатели (`T`)**: Копируется сам указатель (адрес в памяти).
Поскольку при передаче копируется только этот небольшой дескриптор, а не все данные, изменения, сделанные с данными по этому указателю внутри функции, будут видны и снаружи.
Пример со срезом:
func modifySlice(s []int) {
// Изменяем элемент базового массива, на который указывает срез
s[0] = 100
}
func main() {
slice := []int{1, 2, 3}
modifySlice(slice) // Копируется дескриптор среза, а не массив
fmt.Println(slice) // Вывод: [100 2 3]
}