Ответ
В Go ссылочные типы — это типы, которые хранят ссылку (адрес) на данные в памяти, а не сами данные напрямую. Это означает, что при передаче таких типов в функции или присваивании одной переменной другой, копируется ссылка, а не весь объем данных. Изменения, сделанные через одну ссылку, будут видны через другую.
К ним относятся:
-
Указатели (
*T
) — хранят адрес переменной в памяти. Позволяют напрямую изменять значение по адресу.x := 10 p := &x // p теперь указатель на x *p = 20 // Изменяем значение по адресу, на который указывает p fmt.Println(x) // Вывод: 20
-
Срезы (
[]T
) — это дескрипторы, которые ссылаются на базовый массив. Они содержат указатель на первый элемент, длину и емкость.a := []int{1, 2, 3} b := a // b теперь ссылается на тот же базовый массив, что и a b[0] = 99 fmt.Println(a) // Вывод: [99 2 3] (изменение в b повлияло на a)
-
Мапы (
map[K]V
) — это хэш-таблицы, которые управляются через указатель на внутреннюю структуру данных. При передаче мапы, передается ссылка на эту структуру.m := make(map[string]int) m["one"] = 1 n := m // n ссылается на ту же мапу, что и m n["two"] = 2 fmt.Println(m) // Вывод: map[one:1 two:2]
-
Каналы (
chan T
) — используются для безопасного обмена данными между горутинами. Каналы являются ссылочными типами, и при их передаче передается ссылка на структуру канала.ch := make(chan int) go func() { ch <- 42 }() val := <-ch fmt.Println(val) // Вывод: 42
-
Функции — в Go функции являются первоклассными гражданами и могут быть присвоены переменным, переданы как аргументы и возвращены из других функций. Когда вы передаете функцию, вы передаете ссылку на ее исполняемый код.
add := func(a, b int) int { return a + b } operate := func(f func(int, int) int, x, y int) int { return f(x, y) } result := operate(add, 5, 3) fmt.Println(result) // Вывод: 8
-
Интерфейсы — значение интерфейса состоит из двух компонентов: указателя на тип и указателя на значение. Когда вы присваиваете конкретное значение интерфейсу, оно хранится по ссылке.
type Greeter interface { Greet() string }
type Person struct { Name string } func (p Person) Greet() string { return "Hello, " + p.Name }
var g Greeter p := Person{"Alice"} g = p // g теперь содержит ссылку на p и его тип fmt.Println(g.Greet()) // Вывод: Hello, Alice