← Назад к вопросам

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

1.0 Junior🔥 202 комментариев
#Основы Go

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Референсные типы в Go

В Go существует строгое разделение между значимыми типами (value types) и ссылочными типами (reference types). Референсные типы — это типы данных, которые хранят не само значение, а ссылку на область памяти, где это значение находится. При присваивании или передаче в функцию копируется именно эта ссылка, а не сами данные.

Основные референсные типы в Go:

  1. Срезы (Slices)
    Срез — это легковесная структура данных, предоставляющая доступ к последовательным элементам массива. Срез состоит из трех компонентов: указателя на массив, длины и емкости.

    // Пример работы со срезом
    original := []int{1, 2, 3, 4, 5}
    sliceRef := original[1:3] // Создает новый срез, ссылающийся на тот же массив
    sliceRef[0] = 99          // Изменение отразится на оригинальном массиве
    fmt.Println(original)     // Вывод: [1 99 3 4 5]
    

    Важно: сам срез передается по значению (копируется заголовок среза), но поскольку он содержит указатель на массив, изменения элементов видны во всех копиях.

  2. Карты (Maps)
    Карта — это неупорядоченная коллекция пар ключ-значение. При передаче карты в функцию или присваивании другой переменной копируется только дескриптор карты, а данные остаются в общей куче.

    map1 := make(map[string]int)
    map1["key"] = 10
    map2 := map1              // map2 ссылается на те же данные
    map2["key"] = 20          // Изменение через map2
    fmt.Println(map1["key"])  // Вывод: 20
    
  3. Каналы (Channels)
    Каналы используются для обмена данными между горутинами. При копировании канала создается новая ссылка на тот же канал, позволяющая нескольким горутинам взаимодействовать через него.

    ch := make(chan int, 2)
    chRef := ch               // chRef ссылается на тот же канал
    go func() {
        chRef <- 42           // Отправка данных через chRef
    }()
    value := <-ch             // Получение данных через оригинальный ch
    fmt.Println(value)        // Вывод: 42
    
  4. Указатели (Pointers)
    Хотя технически указатель — это value type, содержащий адрес памяти, его поведение является ссылочным. Указатели позволяют косвенно ссылаться на значения и модифицировать их.

    type Person struct {
        Name string
    }
    p := &Person{Name: "Alice"}
    pRef := p                 // Копируется адрес, обе переменные указывают на один объект
    pRef.Name = "Bob"
    fmt.Println(p.Name)       // Вывод: Bob
    
  5. Функции (Functions)
    Функции в Go являются first-class citizens и могут присваиваться переменным, передаваться и возвращаться из других функций. При этом копируется ссылка на функцию.

    multiplier := func(x int) int { return x * 2 }
    alias := multiplier       // alias ссылается на ту же функцию
    result := alias(5)        // Вызов через alias
    fmt.Println(result)       // Вывод: 10
    

Ключевые особенности референсных типов:

  • Общая память: несколько переменных могут ссылаться на одни и те же данные.
  • Изменяемость: модификация данных через одну переменную видна через все другие ссылки.
  • Нулевое значение: нулевым значением для срезов, карт и каналов является nil — ссылка, не указывающая на данные.
  • Сравнение: карты и срезы нельзя сравнивать оператором == (кроме сравнения с nil). Каналы и указатели можно сравнивать — проверяется, ссылаются ли они на одни и те же данные.

Отличие от значимых типов:

В отличие от референсных типов, значимые типы (базовые типы, массивы, структуры) при присваивании копируют все свои данные. Изменения копии не влияют на оригинал.

// Пример со значимым типом (массив)
arr1 := [3]int{1, 2, 3}
arr2 := arr1       // Полное копирование всех элементов
arr2[0] = 99       // Изменяется только копия
fmt.Println(arr1)  // Вывод: [1 2 3] - оригинал не изменился

Понимание разницы между референсными и значимыми типами критически важно для написания корректных, эффективных и безопасных программ на Go, особенно при работе с конкурентностью, где неявное разделение состояния может привести к data races.

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