> Какие типы данных относятся к мутабельным, а какие к немутируемым (Go)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: Астра
Стек: Go
> Пример ответа
Короткий ответ
В Go мутабельность определяется передачей по ссылке или по значению. Мутабельные типы: slice, map, channel, pointer, function, interface (если динамический тип мутабельный). Иммутабельные: все value-типы - int, float, string, bool, array, struct (если все поля - value-типы). String технически иммутабелен, но при присваивании создаётся новая копия. Важно: мутабельность в Go - это свойство ссылочных типов данных, а не синтаксиса.
Подробное объяснение
В Go нет строгого разделения на mutable/immutable, как в Java или Python. Вместо этого есть ссылочные типы (reference types) и типы-значения (value types).
Мутабельные (ссылочные) типы:
- slice - ссылка на массив, можно менять элементы через индекс, append может перераспределить память
- map - хеш-таблица, можно добавлять/удалять ключи
- channel - можно отправлять и принимать значения
- pointer - можно разыменовать и изменить значение по адресу
- function - можно вызывать, но сама функция неизменяема, мутабельность через замыкания
- interface - хранит указатель на данные, мутабельность зависит от динамического типа
Иммутабельные (value) типы:
- int, int8, int16, int32, int64 - целые числа
- uint, uint8, uint16, uint32, uint64 - беззнаковые
- float32, float64 - числа с плавающей точкой
- complex64, complex128 - комплексные
- bool - логический
- string - строка, иммутабельна по спецификации
- array - массив фиксированной длины, передаётся по значению
- struct - структура, передаётся по значению, если не содержит ссылочных полей
Ключевой момент: при передаче value-типа в функцию создаётся копия. Изменения внутри функции не влияют на оригинал. При передаче ссылочного типа копируется только заголовок (slice header, map header), но данные общие.
String - особый случай: строка иммутабельна, но при конкатенации создаётся новая строка. Однако байты строки нельзя изменить по индексу - это приведёт к compile error.
На практике
На практике мутабельность влияет на:
- Проектирование API - если функция должна изменить данные, передавайте указатель или slice; если нет - передавайте value
- Гонки данных - мутабельные типы требуют синхронизации при конкурентном доступе
- Производительность - копирование больших struct дорого, но передача ссылок может привести к неожиданным изменениям
- Чистоту кода - иммутабельные данные проще тестировать и отлаживать
Распространённый паттерн: возвращать копию slice, а не оригинал, чтобы защитить внутреннее состояние.
Пример кода
GOpackage mainimport "fmt"type User struct {Name stringAge int}func mutateSlice(s []int) {s[0] = 100 // изменит оригинал}func mutateMap(m map[string]int) {m["key"] = 42 // изменит оригинал}func mutateStruct(u User) {u.Name = "Changed" // не изменит оригинал}func mutateStructPtr(u *User) {u.Name = "Changed" // изменит оригинал}func main() {// slice - мутабельныйnums := []int{1, 2, 3}mutateSlice(nums)fmt.Println(nums) // [100 2 3]// map - мутабельныйdict := map[string]int{"key": 0}mutateMap(dict)fmt.Println(dict) // map[key:42]// struct - иммутабельный при передаче по значениюuser := User{Name: "Alice", Age: 30}mutateStruct(user)fmt.Println(user.Name) // Alice// struct - мутабельный через указательmutateStructPtr(&user)fmt.Println(user.Name) // Changed// string - иммутабельныйstr := "hello"// str[0] = 'H' // compile errorstr = "Hello" // создаётся новая строка}
Как отвечать на собеседовании
Начните с чёткого разделения: ссылочные типы мутабельны, value-типы иммутабельны. Приведите примеры из каждого класса. Упомяните нюанс со string - иммутабельна, но это не значит, что переменную нельзя переназначить. Покажите понимание передачи по значению и по ссылке на примере slice header и struct. Если спросят про производительность - скажите, что копирование value-типов дёшево для маленьких данных, но для больших структур лучше использовать указатели. Упомяните, что в Go нет встроенных иммутабельных коллекций, но можно реализовать через интерфейсы.
Что проверяет интервьюер
Интервьюер проверяет:
- Понимание модели памяти Go
- Различие между ссылочными и value-типами
- Знание поведения slice и map при передаче в функции
- Понимание последствий мутабельности для конкурентности
- Умение объяснить trade-off между копированием и ссылками
- Глубину понимания string как иммутабельного типа
Типичные ошибки
- Утверждение, что string мутабельна, потому что её можно переназначить - это разные вещи
- Путаница между array и slice: array - value-тип, slice - ссылочный
- Непонимание, что struct с полем slice становится частично мутабельной
- Утверждение, что все типы в Go передаются по значению - это верно для заголовков, но данные общие
- Игнорирование того, что map и slice при передаче в функцию могут быть изменены, но сам заголовок копируется
- Смешивание понятий "мутабельность" и "изменяемость переменной" - переменную можно переназначить всегда, но это не делает тип мутабельным
> Похожие задачи по backend
Какие сигналы существуют в операционной системе
Происходит ли копирование данных при передаче слайса и массива в функцию в Go
Можно ли объявить поле так, чтобы оно было примитивом после компиляции
Можно ли расхэшировать объект
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью