Какие знаешь референсные типы

Ответ

В Go все переменные передаются в функции по значению (pass-by-value). Однако некоторые типы данных ведут себя как ссылочные, потому что значением, которое копируется, является не сам набор данных, а небольшой заголовок (дескриптор), содержащий указатель на базовую структуру данных. Изменение этой базовой структуры через копию дескриптора будет видно и в оригинале.

К таким типам относятся:

  1. Срезы (slices)

    • Срез — это структура из трех полей: указатель на нижележащий массив, длина (len) и ёмкость (cap). При передаче среза копируется эта структура, но указатель продолжает указывать на тот же массив.
      a := []int{1, 2, 3}
      b := a // Копируется дескриптор, но не массив
      b[0] = 42 // Изменяется элемент в общем массиве
      // fmt.Println(a[0]) // Выведет 42
  2. Мапы (maps)

    • Мапа — это указатель на внутреннюю хеш-таблицу. При присваивании или передаче в функцию копируется только этот указатель.
      m1 := map[string]int{"a": 1}
      m2 := m1 // m2 и m1 указывают на одну и ту же хеш-таблицу
      m2["a"] = 100 // Изменение видно через m1
      // fmt.Println(m1["a"]) // Выведет 100
  3. Каналы (channels)

    • Канал, как и мапа, является указателем на внутреннюю структуру, управляющую буфером и горутинами.
      ch1 := make(chan int)
      ch2 := ch1 // ch2 и ch1 ссылаются на один и тот же канал
  4. Указатели (pointers)

    • Это явный тип для хранения адреса памяти другой переменной. Они являются основой ссылочного поведения.
      x := 10
      p := &x // p хранит адрес переменной x
      *p = 20 // Разыменование указателя меняет значение x
      // fmt.Println(x) // Выведет 20
  5. Функции (functions)

    • Функциональные значения (замыкания) также являются ссылочным типом. Они представляют собой указатель на код функции и, возможно, на окружение (захваченные переменные).
      f1 := func() { fmt.Println("test") }
      f2 := f1 // f2 ссылается на ту же функцию
      f2()

Особый случай: интерфейсы (interfaces) Интерфейсное значение — это структура из двух указателей: один на информацию о типе, другой — на сами данные. Поэтому они также проявляют ссылочное поведение.